spring-mvc的啟動過程分析

一、Servlet3.0+的容器啟動過程:

(一)、原理級啟動模式:
  1. Servlet3.0+ 的容器啟動時,會掃描項目中的所有庫的META-INF/services/javax.servlet.ServletContainerInitializer文件的內(nèi)容
  2. 在spring-web.jar下有此文件,文件內(nèi)容:
    org.springframework.web.SpringServletContainerInitializer
    此類為Spring的實現(xiàn),是實現(xiàn)了ServletContainerInitializer的子類,類的聲明如下:
@HandlesTypes({WebApplicationInitializer.class})
public class SpringServletContainerInitializer implements ServletContainerInitializer {...
  1. @HandlesTypes指明了此class要處理的目標(biāo)class是:WebApplicationInitializer.class,即以下方法中的set中的class類型
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
  1. onStartup方法的處理邏輯如下:
    (1)掃描classpath中的WebApplicationInitializer實現(xiàn)類
    (2)將其反射生成對象,調(diào)用其方法public void onStartup(ServletContext servletCxt),并將ServletContext對象傳入到其實現(xiàn)方法中。
    (3)而onStartup方法,即為SpringMVC提供給開發(fā)者的API部分。
  2. 一個具體的實現(xiàn):
public class MyWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletCxt) {
        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();

        //自定義的配置類,與SpringFramework的結(jié)合點
        ac.register(AppConfig.class);
        //完成一些Bean的自動化裝配,但會覆蓋@EnableMVC,所以盡量不要使用
       // ac.refresh();

        //自定義的配置文件,與SpringFramework的結(jié)合點(與配置類二選一)
       // XmlWebApplicationContext ac = new XmlWebApplicationContext();
        //ac.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

以上代碼如何添加Filter?

//OpenSessionInViewFilter  
OpenSessionInViewFilter hibernateSessionInViewFilter = new OpenSessionInViewFilter();  
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter(  
                "hibernateFilter", hibernateSessionInViewFilter);  
filterRegistration.addMappingForUrlPatterns(  
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/"); 

AppConfig.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "cn.johnyu.otherweb.controller")
public class AppConfig implements WebMvcConfigurer {

}
(二)、父子容器(Context Hierarchy)的啟動模式:
  1. 需求是什么?
    簡單應(yīng)用,只需要由啟動一個WebApplicationContext就可足夠了,但如果需要多個WebApplicationContext就難以應(yīng)付共享bean的需要了,此時可以采用Context Hierarchy的方式:
    Context Hierarchy
  2. 實現(xiàn)手段:
    利用一個由Spring提供的WebApplicationInitializer模板完成此機制。
    使用ConfigClass時:
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { App1Config.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/app1/*" };
    }
      /* 
      * 注冊過濾器,映射路徑與DispatcherServlet一致,路徑不一致的過濾器需要注冊到另外的WebApplicationInitializer中 
      */  
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
            new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}
}

使用ConfigXML時

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
      /* 
      * 注冊過濾器,映射路徑與DispatcherServlet一致,路徑不一致的過濾器需要注冊到另外的WebApplicationInitializer中 
      */  
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
            new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}

二、經(jīng)典的Servlet2.X方式

在WEB-INF/web.xml中

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容