SpringBoot——MVC自动配置原理
文章目录
- SpringBoot——MVC自动配置原理
- 1、ContentNegotiatingViewResolver配置原理
- 2、配置格式化转换器
- 3、配置视图控制器
- 4、@EnableWebMvc
springboot为springmvc提供了自动配置,可以很好地用于大多数应用程序。
这些自动配置在Spring默认设置的基础上进行了扩展,可以参考springboot官方文档。
文档链接:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-spring-mvc
下面内容截取自官方文档,很详细的说明了pringboot为springmvc自动装配了什么功能,然后又扩展了哪些功能,并且如何使用扩展的功能:
// 自动配置在Spring默认设置的基础上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
// 包含视图解析器
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
// 支持静态资源文件夹的路径,以及webjars
Support for serving static resources, including support for WebJars
//自动注册了Converter: 转换器,这就是我们网页提交数据到后台自动封装成为对象的东西,比如把"1"字符串自动转换为int类型
// Formatter:格式化器,比如页面给我们了一个2019-8-10,它会给我们自动格式化为Date对象
Automatic registration of Converter, GenericConverter, and Formatter beans.
// HttpMessageConverters
// SpringMVC用来转换Http请求和响应的的,比如我们要把一个User对象转换为JSON字符串;
Support for HttpMessageConverters (covered later in this document).
// 定义错误代码生成规则的
Automatic registration of MessageCodesResolver (covered later in this document).
// 首页定制
Static index.html support.
// 图标定制
Custom Favicon support (covered later in this document).
// 初始化数据绑定器:帮我们把请求数据封装到JavaBean中!
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
//=================================扩展mvc功能============================
/*
如果您希望保留Spring Boot MVC功能,并且希望添加其他MVC配置(拦截器、格式化程序、视图控制器和其他功能),则可以添加自己的@configuration类,类型为webmvcconfiguer,但不添加@EnableWebMvc。如果希望提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,则可以声明WebMVCregistrationAdapter实例来提供此类组件。
*/
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.
// 如果您想完全控制Spring MVC,可以添加自己的@Configuration,并用@EnableWebMvc进行注释。
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.
1、ContentNegotiatingViewResolver配置原理
以前在SpringMVC中,视图解析器我们需要在resources目录下的applicationContext.xml文件中手动配置,如下所示:
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 后缀 -->
<property name="suffix" value=".jsp" />
</bean>
但在springboot中,已经帮springmvc自动装配了ContentNegotiatingViewResolver类,ContentNegotiatingViewResolver视图解析器是Spring MVC 中常用的一个视图解析器。
ContentNegotiatingViewResolver类的源码如下:
public class ContentNegotiatingViewResolver extends WebApplicationObjectSupport
implements ViewResolver, Ordered, InitializingBean {
//只要实现了视图解析器ViewResolver的类就可以看做视图解析器
ContentNegotiatingViewResolver重写ViewResolver接口的方法,源码如下:
获取候选的视图的具体实现是怎么样的呢?点进去继续分析源码:
所以:
编写配置类手动实现视图解析器
package com.cheng.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//扩展springmvc的配置
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//注入到spring中
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//自定义一个视图解析器,只要实现了视图解析器ViewResolver的类就可以看做视图解析器
public static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
return null;
}
}
}
我们想查看自定义的视图解析器有没有起作用,只要在DispatcherServlet类的doDisoatch方法上打个断点,然后启动SpringBoot程序,随便访问一个页面,debug一下
发现我们自定义的视图解析器起作用了
总结:
- ContentNegotiatingViewResolver这个视图解析器就是用来组合所有的视图解析器的,它会返回最合适的视图解析器,所以ContentNagotiatingViewResolver自己并不解析视图,而是委派给其他的视图解析器。
- 如果我们想自定义一些功能,只要写这个组件,然后将它交给springboot,springboot会帮我们自动装配!
2、配置格式化转换器
配置Formatter格式转换器
格式化器在application.properties中的配置:
@Deprecated
@DeprecatedConfigurationProperty(replacement = "spring.mvc.format.date")
public String getDateFormat() {
return this.format.getDate();
}
测试:
#默认日期格式
spring.mvc.format.date=dd/MM/yyyy
#自定义日期格式
spring.mvc.format.date=dd-MM-yyyy
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;
如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
3、配置视图控制器
package com.cheng.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Locale;
//扩展springmvc的配置
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
//增加视图控制器
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//输入cheng请求,就会跳转到test.html页面
registry.addViewController("/cheng").setViewName("test");
}
}
启动测试,成功跳转!
4、@EnableWebMvc
在官方文档中有这样一句话:如果想扩展springmvc的配置,可以添加自己的webmvcconfiguer类型的@configuration
类,但不添加@EnableWebMvc。
现在来分析一下,为什么不能加上@EnableWebMvc
呢?
首先看一下@EnableWebMvc
的组成:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
@EnableWebMvc
只导入了一个DelegatingWebMvcConfiguration
类,点进去分析DelegatingWebMvcConfiguration
:
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
DelegatingWebMvcConfiguration
又继承了WebMvcConfigurationSupport
这个类;
我们再看一下WebMvcAutoConfiguration
(自动装配MVC)的源码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
源码中存在这个注解:@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
:当存在WebMvcConfigurationSupport
这个类的时候,mvc的自动配置会失效,所以不能加@EnableWebMvc
!