0


SpringBoot——MVC原理

优质博文:IT-BLOG-CN

一、SpringMVC自动配置

SpringMVC auto-configuration

SpringBoot

自动配置好了

SpringMVC

。以下是

SpringBoot

SpringMVC

的默认配置:[

WebMvcAutoConfiguration

]
【1】包括

ContentNegotiatingViewResolver

BeanNameViewResolver

如下:

@Bean@ConditionalOnBean({ViewResolver.class})@ConditionalOnMissingBean(
    name ={"viewResolver"},
    value ={ContentNegotiatingViewResolver.class})//存在于 WebMvcAutoConfiguration.javapublicContentNegotiatingViewResolverviewResolver(BeanFactory beanFactory){ContentNegotiatingViewResolver resolver =newContentNegotiatingViewResolver();
    resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
    resolver.setOrder(-2147483648);return resolver;}//进入ContentNegotiatingViewResolver对象,查找解析视图的方法resolveViewName()publicViewresolveViewName(String viewName,Locale locale)throwsException{RequestAttributes attrs =RequestContextHolder.getRequestAttributes();Assert.state(attrs instanceofServletRequestAttributes,"No current ServletRequestAttributes");List<MediaType> requestedMediaTypes =this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());if(requestedMediaTypes !=null){//获取候选的视图对象List<View> candidateViews =this.getCandidateViews(viewName, locale, requestedMediaTypes);//选择最适合的视图对象View bestView =this.getBestView(candidateViews, requestedMediaTypes, attrs);if(bestView !=null){return bestView;}}//进入上面的getCandidateViews()方法,查看获取的视图解析器,发现SpringBoot是将所有的视图解析器获取到viewResolvers,挨个遍历获取。privateList<View>getCandidateViews(String viewName,Locale locale,List<MediaType> requestedMediaTypes)throwsException{List<View> candidateViews =newArrayList();Iterator var5 =this.viewResolvers.iterator();while(var5.hasNext()){

【2】自动配置了

ViewResolver

(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
【3】

ContentNegotiatingViewResolver

:组合所有的视图解析器的;

//进入ContentNegotiatingViewResolver发现初始化视图解析器的时候,是从容器中BeanFactoryUtils获取所有的视图解析器。
protected void initServletContext(ServletContext servletContext) {
    Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(
        this.getApplicationContext(), ViewResolver.class).values();
    if(this.viewResolvers == null) {

【4】如何定制:我们可以自己给容器中添加一个视图解析器;自动的将其组合进来;

@Bean@ConditionalOnProperty(prefix ="spring.mvc", name ="date‐format")//在文件中配置日期格式化的规则publicFormatter<Date>dateFormatter(){returnnewDateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件            }//举个栗子如下://可以自定义一个视图解析器,放入容器,springboot就会自动识别,继承viewreserve@BeanpublicMyViewmyView(){returnnewMyView();}//需要实现ViewResolver接口privatestaticclassMyViewimplementsViewResolver{@OverridepublicViewresolveViewName(String s,Locale locale)throwsException{returnnull;}}

【5】服务对静态资源的支持,静态资源文件夹路径,

webjars

等。静态首页访问,自定义

favicon.ico

图标文件的支持。
【6】自动注册了

of Converter

,

GenericConverter

,

Formatter beans


 ○

Converter

:转换器;

public String hello(User user)

:类型转换使用

Converter

String

int

等等。
 ○

Formatter

格式化器;

2017.12.17===Date

,源码如下:可以看到格式可以通过

spring.mvc.date-format

调整。

@Bean@ConditionalOnProperty(
    prefix ="spring.mvc",
    name ={"date-format"})publicFormatter<Date>dateFormatter(){returnnewDateFormatter(this.mvcProperties.getDateFormat());}

 ○ 自己添加的格式化器转换器,我们只需要放在容器中即可,上面代码块有演示。
【7】支持

HttpMessageConverters


 ○

HttpMessageConverter

SpringMVC

用来转换

Http

请求和响应的;

User

Json

方式写出去;
 ○

HttpMessageConverters

是从容器中确定;获取所有的

HttpMessageConverter


 ○ 自己给容器中添加

HttpMessageConverter

,只需要将自己的组件注册容器中[

@Bean

,

@Component

]
【8】自动注册

MessageCodesResolver

,定义错误代码生成规则。自动使用

ConfigurableWebBindingInitializer

类;

protectedConfigurableWebBindingInitializergetConfigurableWebBindingInitializer(){return(ConfigurableWebBindingInitializer)this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);}

它是从容器中获取

ConfigurableWebBindingInitializer

的,从而可知,我们可以配置一个

ConfigurableWebBindingInitializer

来替换默认的(添加到容器),如果没有配置会初始化一个

Web

数据绑定器:

//初始化Web数据绑定器,作用就是将请求数据绑定到JavaBean中,参数等,涉及数据转换等等protectedConfigurableWebBindingInitializergetConfigurableWebBindingInitializer(){ConfigurableWebBindingInitializer initializer =newConfigurableWebBindingInitializer();
    initializer.setConversionService(this.mvcConversionService());
    initializer.setValidator(this.mvcValidator());
    initializer.setMessageCodesResolver(this.getMessageCodesResolver());return initializer;}

【9】

org.springframework.boot.autoconfigure.web

web

的所有自动场景;上面能够得到的主要思想就是:如何修改

Springboot

的默认配置:
 1)、在自动配置很多组件的时候,先看容器中有木有用户自己配置的(@Bean,@Component)如果有就是用用户配置的,如果没有就是用自动配置的,因为底层使用了@ConditionalOnMiss注解来判断,容器中是否已经存在此类配置。
 2)、如果有些组件可以配置多个,比如视图解析器(ViewResolver)将用户配置的和自己默认的组合起来。

扩展 SpringMVC: 官方解释:If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to provide such components.

【1】根据我们之前的配置

xml

来进行扩展:

<mvc:view‐controllerpath="/hello"view‐name="success"/><mvc:interceptors><mvc:interceptor><mvc:mappingpath="/hello"/><bean></bean></mvc:interceptor></mvc:interceptors>

【2】

SpringBoot

编写一个配置类

@Configuration

,继承

WebMvcConfigurerAdapter

类型,不能标注

@EnableWebMvc

。 继承抽象类既保留了所有的自动配置,也能用我们扩展的配置;

//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能@ConfigurationpublicclassMyMvcConfigextendsWebMvcConfigurerAdapter{@OverridepublicvoidaddViewControllers(ViewControllerRegistry registry){// super.addViewControllers(registry);//浏览器发送 /yintong 请求来到 success ,视图映射,当没有业务逻辑的时候就比较方便
        registry.addViewController("/yintong").setViewName("success");}}

原理:
【1】

WebMvcAutoConfiguration

SpringMVC

的自动配置类;
【2】在做其他自动配置时会导入;

@Import(EnableWebMvcConfiguration.class)

@ConfigurationpublicstaticclassEnableWebMvcConfigurationextendsDelegatingWebMvcConfiguration{privatefinalWebMvcConfigurerComposite configurers =newWebMvcConfigurerComposite();//从容器中获取所有的WebMvcConfigurer    @Autowired(required =false)publicvoidsetConfigurers(List<WebMvcConfigurer> configurers){if(!CollectionUtils.isEmpty(configurers)){this.configurers.addWebMvcConfigurers(configurers);//一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;      @OverridepublicvoidaddViewControllers(ViewControllerRegistry registry){for(WebMvcConfigurer delegate :this.delegates){
                     delegate.addViewControllers(registry);}}}}

【3】容器中所有的

WebMvcConfigurer

都会一起起作用;
【4】我们的配置类也会被调用;
【5】效果:

SpringMVC

的自动配置和我们的扩展配置都会起作用;

二、全面接管SpringMVC

让所有

SpringMVC

的自动配置都失效。使用我们需要的配置,需要在配置类中添加

@EnableWebMvc

即可。非常不推荐,不然使用

SpringBoot

开发干嘛,哈哈。

//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能 @EnableWebMvc@ConfigurationpublicclassMyMvcConfigextendsWebMvcConfigurerAdapter{@OverridepublicvoidaddViewControllers(ViewControllerRegistry registry){// super.addViewControllers(registry);         //浏览器发送 /atguigu 请求来到 success                 
        registry.addViewController("/atguigu").setViewName("success");}}

原理: 为什么

@EnableWebMvc

自动配置就失效了?

【1】

@EnableWebMvc

的核心组合注解:

@Import(DelegatingWebMvcConfiguration.class)public@interfaceEnableWebMvc{

【2】我们打开上面导入的

DelegatingWebMvcConfiguration

类,会发现其继承了

WebMvcConfigurationSupport

@ConfigurationpublicclassDelegatingWebMvcConfigurationextendsWebMvcConfigurationSupport{

【3】我们看下

SpringBoot

自动配置的文件,发现如下:

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

,可知当容器中存在

WebMvcConfigurationSupport

类时,就不会导入自动配置的类了,第二步导入的就是这个类。

@Configuration@ConditionalOnWebApplication@ConditionalOnClass({Servlet.class,DispatcherServlet.class,WebMvcConfigurerAdapter.class})//容器中没有这个组件的时候,这个自动配置类才生效@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE+10)@AutoConfigureAfter({DispatcherServletAutoConfiguration.class,ValidationAutoConfiguration.class})publicclassWebMvcAutoConfiguration{

【4】

@EnableWebMvc

WebMvcConfigurationSupport

组件导入进来;
【5】导入的

WebMvcConfigurationSupport

只是

SpringMVC

最基本的功能;

结论:

SpringBoot

中会有非常多的

xxxConfigurer

帮助我们进行扩展配置。同时,在

SpringBoot

中也会有很多的

xxxCustomizer

帮助我们进行定制配置。

标签: spring boot mvc 后端

本文转载自: https://blog.csdn.net/zhengzhaoyang122/article/details/134588261
版权归原作者 程序猿进阶 所有, 如有侵权,请联系我们删除。

“SpringBoot——MVC原理”的评论:

还没有评论