2017年12月26日 星期二

Java Spring - 使用其他方式設定DispatcherServlet及ContextLoaderListener

  •  透過其他方式set up DispatcherServlet and ContextLoaderListener
    • 可能需要額外的Servlet、filter
    • 需要對DispatcherServlet做額外config
  • 自行定義個DispatcherServlet configuration
    • 除了以下三種必須被override的method以外,其實還有更多可以被override的method
      • getRootConfigClasses
      • getServletConfigClasses
      • getServletMappings
    • 如:
      • customizeRegistration()
        • 當DispatcherServlet註冊到Servlet container後,就會呼叫customizeRegistration,並將Servlet註冊以後得到的Registration.Dynamic 傳遞進去。透過override此method,可以對DispatcherServlet進行額外config
        @Override
        protected void customizeRegistration(Dynamic registration) {
         registration.setMultipartConfig(
          new MultipartConfigElement("/tmp/spittr/uploads")); //設定暫存目錄
        }
        
        • 透過setLoadOnStartup()設定load-on-startup優先權
        • 透過setInitParameter()設定初始化parameter
        • 透過setMultipartConfig() config Servlet3.0對multipart的support
  • Adding additional Servlet & Filter
    • AbstractAnnotationConfigDispatcherServletInitializer會自行create DispatcherServlet和ContextLoaderListener.
      • 問:如果想要建立Servlet、Filter及Listener時
    • 使用Java的initializer可以定義任意數量的initializer classes。因此如果想要註冊其他component,則只需create一個新的initializer
    • 最簡單的方法: implement Spring WebApplicationInitializer interface
    • import javax.servlet.ServletContext;
      import javax.servlet.ServletException;
      import javax.servlet.ServletRegistration.Dynamic;
      import org.springframework.web.WebApplicationInitializer;
      import com.myapp.MyServlet;
      
      public class MyServletInitializer implements WebApplicationInitializer {
      
          @Override
          public void onStartup(ServletContext servletContext) throws ServletException {
              Dynamic myServlet = servletContext.addServlet("myServlet", MyServlet.class); // 註冊servlet
              myServlet.addMapping("/custom/**"); // mapping servlet
          }
      }
      
    • 也可以註冊Listener & Filter
    • @Override
      public void onStartup(ServletContext servletContext) throws ServletException {
       javax.servlet.FilterRegistration.Dynamic filter = servletContext.addFilter("myFilter", MyFilter.class); // 註冊filter
       filter.addMappingForUrlPatterns(null, false, "/custom/*"); // mapping servlet
      }
      
    • 若只是register Filter,且此filter會mapping至DispatcherServlet,則AbstractAnnotationConfigDispatcherServletInitializer提供一個簡單override的方法
    • @Override
      protected Filter[] getServletFilters() {
       return new Filter[] {
        new MyFilter() // 不需要特別mapping,因為override這個method的所有return filter都會mapping到DispatcherServlet內
       };
      }
      
  • 傳統使用web.xml declare DispatcherServlet
    • <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring/root-context.xml</param-value>
        </context-param>
        <listener>
          <listener-class>
            org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <servlet>
          <servlet-name>appServlet</servlet-name>
          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
          <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
          <servlet-name>appServlet</servlet-name>
          <url-pattern>/</url-pattern>
        </servlet-mapping>
      </web-app>
      
      • context-param: 設定root context config file
      • listener-class: register ContextLoader Listener
      • servlet: register Dispatcher servlet
    • ContextLoaderListener& DispatcherServlet都有各自的Spring application context
    • ContextLoaderListener會從/WEB-INF/spring/root-context.xml load bean definition
    • DispatcherServlet會根據Servlet名字找到文件,因此會從/WEB-INF/appServlet-context.xml file中load application context
    • 也可以自行指定config location
    • <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>
            /WEB-INF/spring/appServlet/servlet-context.xml
          </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      
    • 要在Spring MVC中使用基於Java的配置,需要告訴ContextLoaderListener及DispatcherServlet使用AnnotationConfigWebApplicationContext,這是一個WebApplicationContext的implement class,他會load Java config class,而不是使用XML
      • 方法:設定contextClass context parameter
      • DispatcherServlet的initial parameters
    • 以下範例使用基於Java的Spring configuration 
    • <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.5"
        xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
            http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <context-param>
          <param-name>contextClass</param-name>
          <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext //使用Java config
        </param-value>
      </context-param>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.habuma.spitter.config.RootConfig</param-value>
       </context-param>//指定root config class
      <listener>
        <listener-class>
          org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
      <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <init-param>
          <param-name>contextClass</param-name>
          <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext//使用Java config
            </param-value>
          </init-param>
          <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value> // 指定DispatcherServlet config
              com.habuma.spitter.config.WebConfigConfig
            </param-value>
          </init-param>
          <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
          <servlet-name>appServlet</servlet-name>
          <url-pattern>/</url-pattern>
        </servlet-mapping>
      </web-app>

沒有留言:

張貼留言