WebMvc自动配置流程讲解
原理分析
- 启动springMvc内置的视图解析器
ContentNegotiatingViewResolver
和BeanNameViewResolver
- ContentNegotiatingViewResolver :并不会解析视图本身,而是委托其他的视图解析器进行解析
- 所有的视图解析器,都会根据返回的视图名称进行解析视图
- ContentNegotiatingViewResolver :并不会解析视图本身,而是委托其他的视图解析器进行解析
@Override
@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 = getMediaTypes(((ServletRequestAttributes) attrs).getRequest());
if (requestedMediaTypes != null) {
// 获得所有匹配的视图
List<View> candidateViews = getCandidateViews(viewName, locale, requestedMediaTypes);
// 获取最终的视图
View bestView = getBestView(candidateViews, requestedMediaTypes, attrs);
if (bestView != null) {
return bestView;
}
}
委派给其他解析器进行解析
@Override
protected void initServletContext(ServletContext servletContext) {
Collection<ViewResolver> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(obtainApplicationContext(), ViewResolver.class).values();
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList<>(matchingBeans.size());
for (ViewResolver viewResolver : matchingBeans) {
if (this != viewResolver) {
this.viewResolvers.add(viewResolver);
}
}
}
由以上的代码可以得出结论,它是从Spring IOC容器中获得viewResolver,我们可以自己定制一个viewResolver,ContentNegotiatingViewResolver
也会帮我们委派解析
BeanNameViewResolver
- 根据handler方法返回的视图名称 对应到具体视图并解析(定义一个相同名称的类,此类继承一个view(abstractXlsView等等)的接口去生成一个视图)
支持提供静态资源,包括对WebJars的支持
WebJars将静态资源放在jar包中进行访问
以前要访问jpg、css、js等这些静态资源文件,需要在web.xml配置,在springboot中不需要配置,只需要放到指定的文件夹中就可以读取出来(约定大于配置)
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocations()); if (this.servletContext != null) { ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION); registration.addResourceLocations(resource); } }); }
为什么我们访问http://localhost:8080/image/timssg.jpg也可以访问到图片呢?
public static class Resources { private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }; /** * Locations of static resources. Defaults to classpath:[/META-INF/resources/, * /resources/, /static/, /public/]. */ private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
- 上述代码表示,当图片位于上面的文件中也是可以被读取出来的
自动注册
Converter
,GenericConverter
和Formatter
Bean类支持
HttpMessageConverters
HttpMessageConverters
负责http请求和响应的报文处理
自动注册
MessageCodesResolver
- 修改错误下的格式转换出错类型转换出错的错误代码
静态
index.html
支持在springboot中可以直接返回html的视图
因为在自动WebMvcAutoConfiguration配置类配置
所以就可以通过在配置文件中完成配置
@Bean @ConditionalOnMissingBean public InternalResourceViewResolver defaultViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix(this.mvcProperties.getView().getPrefix()); resolver.setSuffix(this.mvcProperties.getView().getSuffix()); return resolver; }
@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 { /** * The default Spring MVC view prefix. */ public static final String DEFAULT_PREFIX = ""; /** * The default Spring MVC view suffix. */ public static final String DEFAULT_SUFFIX = "";
自动使用
ConfigurableWebingingInitializer
bean