Back to Javatutorial

SpringMVC的Demo与@EnableWebMvc注解

docs/Spring全家桶/SpringMVC源码分析/SpringMVC的Demo与@EnableWebMvc注解.md

1.0.017.7 KB
Original Source

1. demo ׼

Ϊ˸õط springmvc Դ룬Ҫ׼һ springmvc demo demo Ƿ spring-learn ģ顣

1. tomcat

tomcat 8 ֮tomcat ṩ˶аҪʱֱͿˣӦ gradle :

optional("org.apache.tomcat.embed:tomcat-embed-core")

spring Ŀ build.gradle УѾ tomcat-embed-core-9.0.29.jar spring-learn ģʱָ汾

2. ׼

package org.springframework.learn.mvc.demo01;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Component
@ComponentScan("org.springframework.learn.mvc.demo01")
@EnableWebMvc
public class MvcConfig {

}

Ϊ MvcConfigָĿİɨ·Լͨ @EnableWebMvc mvc ܡ

3. ʵ WebApplicationInitializer

package org.springframework.learn.mvc.demo01;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(MvcConfig.class);

        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/*");
    }
}

spring ṩһӿ WebApplicationInitializerʵָýӿʱ onStartup(...) д spring applicationContextȻ servelet ע DispatcherServlet

4. ׼ controller

package org.springframework.learn.mvc.demo01;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {

    @RequestMapping("/hello")
    public String hello() {
         System.out.println("hello!!!");
         return "hello world!";
    }
}

׼һ򵥵 controllerһַ "hello world".

5.

ˣ

package org.springframework.learn.mvc.demo01;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleListener;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;

public class MvcDemo01Main {

    public static void main(String[] args) throws Exception {
        Tomcat tomcat = new Tomcat();

        Connector connector = new Connector();
        connector.setPort(8080);
        connector.setURIEncoding("UTF-8");
        tomcat.getService().addConnector(connector);

        Context context = tomcat.addContext("", System.getProperty("java.io.tmpdir"));
        LifecycleListener lifecycleListener = (LifecycleListener) 
                Class.forName(tomcat.getHost().getConfigClass())
                .getDeclaredConstructor().newInstance();
        context.addLifecycleListener(lifecycleListener);
        tomcat.start();
        tomcat.getServer().await();
    }
}

main УҪ tomcat ߼

У£

̨

ҳ淵أ

Կһ򵥵 springmvc Ŀʹˡ

2. servlet 3.0

¹ϵ springmvc Ŀһ⼸ xml ļ

  • web.xmlservlet ļ web ʱIJԼ servlet/listener/filter;
  • spring.xmlspring ļҪ spring bean.
  • spring-mvc.xmlspringmvc ļ mvc ص beanļϴص beanͼ beancontroller ·ȡ

Ŀʱȼ web.xml web.xml м spring ã spring

demo УǷֲ ûЩã web.xml ļûУô web Ŀôأ

servlet 3.0 ֮ṩһ spi 淶spring ʵ£

  1. spring-web ģ /src/main/resources/META-INF/services/ ļ£ļ javax.servlet.ServletContainerInitializer
org.springframework.web.SpringServletContainerInitializer

  1. org.springframework.web.SpringServletContainerInitializer ʵ servlet 淶
// @HandlesTypes עservlet淶ʾ webAppInitializerClass Ϊ WebApplicationInitializer.class
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

    /*
     * д ServletContainerInitializer  onStartup 
     * Ҫʵ spring ṩ WebApplicationInitializer.classȻִ onStartup 
     *
     * Set<Class<?>> webAppInitializerClasses еΪ WebApplicationInitializer.class
     *  @HandlesTypes עָ
     */
    @Override
    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {

        List<WebApplicationInitializer> initializers = new LinkedList<>();

        if (webAppInitializerClasses != null) {
            for (Class<?> waiClass : webAppInitializerClasses) {
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                        WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                       // ʹ÷ʵ WebApplicationInitializer ʵ࣬ӵ initializers 
                        initializers.add((WebApplicationInitializer)
                                ReflectionUtils.accessibleConstructor(waiClass).newInstance());
                    }
                    catch (Throwable ex) {
                        ...
                    }
                }
            }
        }

        servletContext.log(initializers.size() + " ...");
        // ʵOrderdӿڣע @Order ע⣬ʵ PriorityOrderd ӿ
        AnnotationAwareOrderComparator.sort(initializers);
        for (WebApplicationInitializer initializer : initializers) {
           //  WebApplicationInitializer ʵonStartup
           initializer.onStartup(servletContext);
        }
    }

}

  1. WebApplicationInitializer ʵ demo ж WebApplicationInitializer ʵ֣
package org.springframework.learn.mvc.demo01;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    /*
     *  spring Ŀ
     */
    @Override
    public void onStartup(ServletContext servletContext) {
        //  spring  ApplicationContext
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(MvcConfig.class);

        //  DispatcherServlet  servlet 
        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/*");
    }
}

ִй£

ɴˣspring ˡ

3. @EnableWebMvc

demo Уͨ @EnableWebMvc mvc ܣôעʲôأǽ EnableWebMvc

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

Կעͨ @Import ע DelegatingWebMvcConfiguration.class DelegatingWebMvcConfiguration:

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    ...

}

@Configuration ע⣬Ǹ̳࣬е WebMvcConfigurationSupport``WebMvcConfigurationSupport Ϊ "mvc ֧"ô mvc صõġ

Ϊ˸õطȽܼࣺ

  1. DelegatingWebMvcConfiguration @EnableWebMvcWebMvcConfigurationSupport ࣬д WebMvcConfigurationSupport ṩ÷

    /*
     * @ConfigurationǸ
     * extends WebMvcConfigurationSupport̳WebMvcConfigurationSupport
     */
    @Configuration(proxyBeanMethods = false)
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    
        // WebMvcConfigurerComposite  WebMvcConfigurer ϣᵽ
        private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
    
        /**
         * configurers
         * @Autowiredע⣬ʾspringеWebMvcConfigurer bean Ϊ
         * configurersֵ Ȼø÷
         */
        @Autowired(required = false)
        public void setConfigurers(List<WebMvcConfigurer> configurers) {
            if (!CollectionUtils.isEmpty(configurers)) {
                this.configurers.addWebMvcConfigurers(configurers);
            }
        }
    
        /**
         * PathMatch
         */
        @Override
        protected void configurePathMatch(PathMatchConfigurer configurer) {
            //  WebMvcConfigurerComposite ķ
            this.configurers.configurePathMatch(configurer);
        }
    
        // ÷Ҳǵ WebMvcConfigurerComposite Ӧķõ
        ...
    
    }
    
    
  2. WebMvcConfigurerComposite``WebMvcConfigurer ϣ

    /**
     * ʵ WebMvcConfigurer
     */
    class WebMvcConfigurerComposite implements WebMvcConfigurer {
    
        // delegatesΪ WebMvcConfigurer ļ
        private final List<WebMvcConfigurer> delegates = new ArrayList<>();
    
        /*
         * DelegatingWebMvcConfiguration#setConfigurers
         * ǰѴconfigurersӵdelegates(ҲWebMvcConfigurer)
         */
        public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
            if (!CollectionUtils.isEmpty(configurers)) {
                this.delegates.addAll(configurers);
            }
        }
    
        /**
         * ʱdelegates(ҲWebMvcConfigurer)õ
         * еÿһWebMvcConfigurer
         */
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
            for (WebMvcConfigurer delegate : this.delegates) {
                delegate.configurePathMatch(configurer);
            }
        }
    
        // ƣʡ
        ...
    }
    
    
  3. WebMvcConfigurerspringmvc ýӿڣṩ˷dz

    public interface WebMvcConfigurer {
    
        default void configurePathMatch(PathMatchConfigurer configurer) {
        }
    
        default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        }
    
        default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        }
    
        ...
    }
    
    
  4. WebMvcConfigurationSupportspringmvc ֧

    /**
     * ʵawareӿ
     */
    public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
    
        //=================  XxxAware ӿڵķ =================
        @Override
        public void setApplicationContext(@Nullable ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }
    
        @Override
        public void setServletContext(@Nullable ServletContext servletContext) {
            this.servletContext = servletContext;
        }
    
        //================= @Bean spring bean =================
        @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping(...) {
            RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
            mapping.setOrder(0);
            // getInterceptors(...) ȡ interceptors¿
            mapping.setInterceptors(getInterceptors(conversionService, resourceUrlProvider));
            mapping.setContentNegotiationManager(contentNegotiationManager);
            // getCorsConfigurations(...) ȡCorsã¿
            mapping.setCorsConfigurations(getCorsConfigurations());
            // getPathMatchConfigurer(...) ȡPathMatchã¿
            PathMatchConfigurer configurer = getPathMatchConfigurer();
    
            ...
    
            return mapping;
        }
        ...
        //================= get xxx ÷springṩĬãԶ =======
        // ȡ interceptors
        protected final Object[] getInterceptors(
                FormattingConversionService mvcConversionService,
                ResourceUrlProvider mvcResourceUrlProvider) {
            if (this.interceptors == null) {
                InterceptorRegistry registry = new InterceptorRegistry();
                // ÷ interceptor¿
                addInterceptors(registry);
                registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService));
                registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider));
                this.interceptors = registry.getInterceptors();
            }
            return this.interceptors.toArray();
        }
    
        // ȡCors
        protected final Map<String, CorsConfiguration> getCorsConfigurations() {
            if (this.corsConfigurations == null) {
                CorsRegistry registry = new CorsRegistry();
                // ÷ CorsMapping¿
                addCorsMappings(registry);
                this.corsConfigurations = registry.getCorsConfigurations();
            }
            return this.corsConfigurations;
        }
    
        // ȡPathMatch
        protected PathMatchConfigurer getPathMatchConfigurer() {
            if (this.pathMatchConfigurer == null) {
                this.pathMatchConfigurer = new PathMatchConfigurer();
                configurePathMatch(this.pathMatchConfigurer);
            }
            return this.pathMatchConfigurer;
        }
    
        ...
    
        //================= ÷ʵ =================
        // Զ Interceptorʵ
        protected void addInterceptors(InterceptorRegistry registry) {
        }
    
        // Զ CorsMappingʵ
        protected void addCorsMappings(CorsRegistry registry) {
        }
    
        // Զ PathMatch
        protected void configurePathMatch(PathMatchConfigurer configurer) {
        }
        ...
    
    }
    
    

    ԿķΪࣺ

    • XxxAware ķXxxAware ӿ spring ṩbean ʼʱص
    • @Bean עķ spring bean bean ʱ getXxx
    • getXxx ȡ÷ڸ÷У spring ṩĬãԼ addXxx/configureXxx Զã
    • addXxx/configureXxx ʵ֣ springmvc Զá

ܽ 4 Ĺϵ

ĸĹϵ@EnableWebMvc ִ̾һĿȻˣܽ£

  1. @EnableWebMvc spring DelegatingWebMvcConfiguration

  2. DelegatingWebMvcConfiguration а @Autowired עķ setConfigurers(List<WebMvcConfigurer>) spring bean лִУΪȡ WebMvcConfigurer bean õ DelegatingWebMvcConfiguration У

  3. DelegatingWebMvcConfiguration ̳ WebMvcConfigurationSupport spring bean лᴦ WebMvcConfigurationSupport @Bean עķַȽ϶࣬ requestMappingHandlerMapping()``mvcPathMatcher ȣЩ smvc Ĺ

  4. ڴ WebMvcConfigurationSupport @Bean עķʱ getXxx() ȡãð spring ṩĬüԶãgetXxx() WebMvcConfigurationSupport

  5. ڵ WebMvcConfigurationSupport#getXxx() ȡԶʱ addXxx()/configureXxx()÷ WebMvcConfigurationSupport ǿշ߼ (Ҳ DelegatingWebMvcConfiguration) ṩյ÷ʽִе 2 ȡ WebMvcConfigurer addXxx()/configureXxx()

ͼʾ

springmvc ܣԶʱǿô:

  1. ʽ 1ʹ @EnableWebMvc ע mvc ܣʵ WebMvcConfigurerԶ

    // ʹ@EnableWebMvcעmvc
    @Component
    @EnableWebMvc
    public class MvcConfig {
        ...
    }
    
    // ʵ WebMvcConfigurerԶ
    @Component
    public class MyWebMvcConfigurer implements WebMvcConfigurer {
    
        // дWebMvcConfigurerԶ
    }
    
    
  2. ʽ 2ʵ WebMvcConfigurationSupport ࣬де÷

    @Component
    public class MyWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
        // д÷Զ
    
    }
    
    

    ַʽʵ WebMvcConfigurer ԶþͲЧˣԶֻ WebMvcConfigurationSupport á

springmvc ṩЩأ WebMvcConfigurer ṩķ

  • configurePathMatch·
  • configureContentNegotiationЭ
  • configureAsyncSupport
  • configureDefaultServletHandlingĬϾ̬Դ
  • addFormattersעԶת
  • addInterceptors
  • addResourceHandlersԴ
  • addCorsMappingsCORS
  • addViewControllersͼת
  • configureViewResolversͼ
  • addArgumentResolversԶ巽
  • addReturnValueHandlersԶ巵ؽ
  • configureMessageConvertersϢתػḲĬע HttpMessageConverter
  • extendMessageConvertersϢתһԶ HttpMessageConverter.
  • configureHandlerExceptionResolvers쳣ת
  • extendHandlerExceptionResolvers쳣ת
  • getValidator:
  • getMessageCodesResolver

ҪֻҪдط ɡ

WebMvcConfigurationSupport Щ Bean @Bean עķ£

  • public RequestMappingHandlerMapping requestMappingHandlerMapping(...)
  • public PathMatcher mvcPathMatcher()
  • public UrlPathHelper mvcUrlPathHelper()
  • public ContentNegotiationManager mvcContentNegotiationManager()
  • public HandlerMapping viewControllerHandlerMapping(...)
  • public BeanNameUrlHandlerMapping beanNameHandlerMapping(...)
  • public RouterFunctionMapping routerFunctionMapping(...)
  • public HandlerMapping resourceHandlerMapping(...)
  • ResourceUrlProvider mvcResourceUrlProvider()
  • public HandlerMapping defaultServletHandlerMapping()
  • public RequestMappingHandlerAdapter requestMappingHandlerAdapter(...)
  • public HandlerFunctionAdapter handlerFunctionAdapter()
  • public FormattingConversionService mvcConversionService()
  • public Validator mvcValidator()
  • public CompositeUriComponentsContributor mvcUriComponentsContributor(...)
  • public HttpRequestHandlerAdapter httpRequestHandlerAdapter()
  • public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter()
  • public HandlerExceptionResolver handlerExceptionResolver(...)
  • public ViewResolver mvcViewResolver(...)
  • HandlerMappingIntrospector mvcHandlerMappingIntrospector()

Щ springmvc õһЩľݾͲչˡ

4. ܽ

ݱȽӣṩһ springmvc demoȻ demo 0 xml ԭ (Ҳ servlet 3.0 淶Ž @EnableWebMvc Ĺܣؽ WebMvcConfigurationSupport á


ԭӣhttps://my.oschina.net/funcy/blog/4696657 ߸ˮƽд֮ӭָԭףҵתϵ߻Ȩҵתע