SpringMvc DispatchServlet各版本初始化

关于SpringMvc dispatchServlet配置

接手过三个不同方式的web项目,spring mvc 配置各有不同,整理一下
  • * 1.基于web.xml方式*
  • 2.基于servlet3.0 注解配置方式
  • 3.spring boot 启动方式

1.基于web.xml方式

最早的方式,基于web.xml配置,通过配置DispatcherServlet实现初始化,如果需要配置spring,另外添加spring ContextLoaderListener,存在双亲上下文的问题

spring 监听器配置
 <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

spring mvc DispatcherServlet配置
<servlet>
    <servlet-name>demoDispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/META-INF/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

2.基于servlet3.0 注解配置方式

基于注解配置spring mvc,不需要再配置web.xml,代码及原理如下:

1.实现方式,自定义WebAppInitializer继承

package ;

import java.util.EnumSet;

import javax.servlet.DispatcherType;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import org.springframework.web.util.IntrospectorCleanupListener;

import com.ly.fn.biz.fq.hybrid.config.ContextConfig;
import com.ly.fn.biz.fq.hybrid.config.ServletConfig;
import com.ly.fn.inf.trace.client.web.CatFilter;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class[] getRootConfigClasses() {
        return new Class[] { ContextConfig.class };
    }

    @Override
    protected Class[] getServletConfigClasses() {
        return new Class[] { ServletConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected void registerContextLoaderListener(ServletContext servletContext) {
        servletContext.addListener(new IntrospectorCleanupListener());
        super.registerContextLoaderListener(servletContext);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        DelegatingFilterProxy delegateFilter = new DelegatingFilterProxy();
        FilterRegistration.Dynamic reg = servletContext.addFilter("filters", delegateFilter);
        reg.addMappingForUrlPatterns(
                EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*");
    }

}

2.配置相关组件,同以前的spring-servlet.xml配置

package ;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "", includeFilters = {
        @Filter(Controller.class), @Filter(ControllerAdvice.class), @Filter(RestController.class) })
public class ServletConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addArgumentResolvers(List argumentResolvers) {
    }

    @Override
    public Validator getValidator() {
        OptionalValidatorFactoryBean optional = new OptionalValidatorFactoryBean();
        optional.setProviderClass(HibernateValidator.class);
        return optional;
    }

    @Bean
    @Autowired
    public SpringTemplateEngine templateEngine(Set templateResolver,
            Set layoutDialect) {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setAdditionalDialects(layoutDialect);
        engine.setTemplateResolvers(templateResolver);
        return engine;
    }

    @Bean
    public IDialect infDialect() {
        return new InfDialect();
    }

    @Bean
    public ServletContextTemplateResolver templateResolver_views() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setCacheable(false);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(1);
        return resolver;
    }

    @Bean
    @Autowired
    public ThymeleafViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(0);
        return resolver;
    }

    @Bean
    public RpcwiredAutoInjectionProcessor rpcwiredProcessor() {
        return new RpcwiredAutoInjectionProcessor();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
    }

    @Override
    public void configureMessageConverters(List> converters) {
        converters.add(new FormHttpMessageConverter());
        converters.add(new ByteArrayHttpMessageConverter());
        converters.add(new StringHttpMessageConverter());
    }

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        super.configureContentNegotiation(configurer);
        configurer.defaultContentTypeStrategy(new DefaultContentNegotiationStrategy());
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/nohup.html").setStatusCode(HttpStatus.OK).setViewName("nohup");
    }

3.启动原理

servlet 3.0 下容器启动后会通过java spi 机制寻找ServletContainerInitializer实现类,
该配置在spring-web jar 包META-INF下
SpringMvc DispatchServlet各版本初始化_第1张图片
文件内容
org.springframework.web.SpringServletContainerInitializer
打开该类,我们会发现其实现了onStartup方法


package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;

import org.springframework.core.annotation.AnnotationAwareOrderComparator;


@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

    @Override
    public void onStartup(Set> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {

        List initializers = new LinkedList();

        if (webAppInitializerClasses != null) {
            for (Class waiClass : webAppInitializerClasses) {
                // Be defensive: Some servlet containers provide us with invalid classes,
                // no matter what @HandlesTypes says...
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                        WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer) waiClass.newInstance());
                    }
                    catch (Throwable ex) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
            return;
        }

        servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
        AnnotationAwareOrderComparator.sort(initializers);
        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }

}

@HandlesTypes(WebApplicationInitializer.class)
onStup方法根据类上的注解找到所有改类型的类作为参数传入,而我们的前面定义的AppInitializer也实现了该接口,
initializers.add((WebApplicationInitializer) waiClass.newInstance());
最终此处实例化我们自定义的启动类,并且在后面执行onStartUp方法
AbstractDispatcherServletInitializer.onStartup中执行了相关servlet的注册registerDispatcherServlet(servletContext);

3.spring boot 方式

篇幅过长,另写

你可能感兴趣的:(SpringMvc DispatchServlet各版本初始化)