美文网首页
spring-mvc的启动过程分析

spring-mvc的启动过程分析

作者: JohnYuCN | 来源:发表于2019-09-26 12:50 被阅读0次

    一、Servlet3.0+的容器启动过程:

    (一)、原理级启动模式:
    1. Servlet3.0+ 的容器启动时,会扫描项目中的所有库的META-INF/services/javax.servlet.ServletContainerInitializer文件的内容
    2. 在spring-web.jar下有此文件,文件内容:
      org.springframework.web.SpringServletContainerInitializer
      此类为Spring的实现,是实现了ServletContainerInitializer的子类,类的声明如下:
    @HandlesTypes({WebApplicationInitializer.class})
    public class SpringServletContainerInitializer implements ServletContainerInitializer {...
    
    1. @HandlesTypes指明了此class要处理的目标class是:WebApplicationInitializer.class,即以下方法中的set中的class类型
    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext) throws ServletException {
    
    1. onStartup方法的处理逻辑如下:
      (1)扫描classpath中的WebApplicationInitializer实现类
      (2)将其反射生成对象,调用其方法public void onStartup(ServletContext servletCxt),并将ServletContext对象传入到其实现方法中。
      (3)而onStartup方法,即为SpringMVC提供给开发者的API部分。
    2. 一个具体的实现:
    public class MyWebApplicationInitializer implements WebApplicationInitializer {
        @Override
        public void onStartup(ServletContext servletCxt) {
            // Load Spring web application configuration
            AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
    
            //自定义的配置类,与SpringFramework的结合点
            ac.register(AppConfig.class);
            //完成一些Bean的自动化装配,但会覆盖@EnableMVC,所以尽量不要使用
           // ac.refresh();
    
            //自定义的配置文件,与SpringFramework的结合点(与配置类二选一)
           // 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. 需求是什么?
      简单应用,只需要由启动一个WebApplicationContext就可足够了,但如果需要多个WebApplicationContext就难以应付共享bean的需要了,此时可以采用Context Hierarchy的方式:
      Context Hierarchy
    2. 实现手段:
      利用一个由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() };
        }
    }
    

    二、经典的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>
    

    相关文章

      网友评论

          本文标题:spring-mvc的启动过程分析

          本文链接:https://www.haomeiwen.com/subject/nibeyctx.html