Spring MVC自动配置
SpringBoot 为 Spring MVC 提供了自动配置,可与大多数应用程序完美配合:
org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java
自动配置在Spring 的默认值上添加的功能:
- 视图解析器:BeanNameViewResolver 和 ContentNegotiatingViewResolver
- 静态资源文件夹路径:支持服务静态资源,包括Webjars
- 转换器、格式化器
- 支持 HttpMessageConverters :SpringMVC 用来转换Http请求和响应
- 定义错误代码成成规则:自动注册MessageCodesResolver
- 静态首页访问
- ...
如果我们想要保留 SpringBoot MVC 的功能,并且需要添加其它 MVC配置(拦截器、格式化程序和视图控制器等),可以添加WebMvcConfigurer 类型的 @Configuration 类,注意不能添加@EnableWebMvc 注解。
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
...
}
如果我们想要全面接管 Spring MVC,可以自定义 添加了@EnableWebMvc 注解的@Configuration 配置类。
视图解析器
根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发或重定向)
- 自动配置了ViewResolver
- ContentNegotiatingViewResolver:组合所有视图解析器
@Bean
@ConditionalOnBean(ViewResolver.class)
@ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(beanFactory.getBean(ContentNegotiationManager.class));
// ContentNegotiatingViewResolver uses all the other view resolvers to locate
// a view so it should have a high precedence
resolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
return resolver;
}
@Nullable
public View resolveViewName(String viewName, Locale locale) throws Exception {
RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
Assert.state(attrs instanceof ServletRequestAttributes, "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;
}
}
protected void initServletContext(ServletContext servletContext) {
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
//ViewResolver.class 从容其中获取所有的视图解析器
所有我们可以自己给容器中添加一个视图解析器,自动的将其组合进来:
@Component
public class MyViewName implements ViewResolver {
@Override
public View resolveViewName(String s, Locale locale) throws Exception {
return null;
}
}
扩展SpringMVC
以前在需要在配置文件中配置:
<mvc:view-controller path="/hello" view-name="success"/>
在SpringBoot 中,编写一个配置类(@Configuration),是WebMvcConfigurer 类型(实现了这个接口),注意不能添加@EnableWebMvc注解
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/hello").setViewName("success");
}
}
这样,SpringBoot 在启用时,SpringMVC的自动配置和我们的扩展配置都会起作用。
如何修改SpringBoot 的默认配置
SpringBoot 在自动配置很多组件时,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置。