美文网首页
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