本文主要介绍SpringBoot:MVC自动配置原理、转换器和格式化器和静态资源处理
一、SpringBoot:MVC自动配置原理
SpringBoot对我们的SpringMVC还做了哪些配置,包括如何扩展,如何定制。
我们能用到的途径:1.阅读源码;2.官方文档
#Spring-MVC自动配置
Spring MVC Auto-configuration
#springboot为springmvc提供了自动配置,可以很好地用于大多数应用程序。
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.
#自动配置在Spring默认设置的基础上添加了以下功能:
The auto-configuration adds the following features on top of Spring’s defaults:
#包含ContentNegotingViewResolver和BeanNameViewResolver bean。
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
#对服务静态资源的支持,包括对webjar的支持(本文后面将介绍)。
Support for serving static resources, including support for WebJars (covered later in this document)).
#自动注册转换器、GenericConverter和格式化程序bean。
Automatic registration of Converter, GenericConverter, and Formatter beans.
#对HttpMessageConverters的支持(本文后面将介绍)。
Support for HttpMessageConverters (covered later in this document).
#MessageCodesResolver的自动注册(本文档后面将介绍)。
Automatic registration of MessageCodesResolver (covered later in this document).
#静态索引.html支持。
Static index.html support.
#自定义Favicon支持(本文档稍后将介绍)。
Custom Favicon support (covered later in this document).
#可配置WebBindingInitializerbean的自动使用(本文后面将介绍)。
Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).
#如果您想保留这些Spring-Boot MVC定制并进行更多MVC定制(拦截器、格式化程序、视图控制器和其他特性),您可以添加自己的WebMvcConfigurer类型的@Configuration类,但不添加@EnableWebMvc。
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.
#如果要提供RequestMappingHandlerMapping、RequestMappingHandlerAdapter或ExceptionHandlerExceptionResolver的自定义实例,并且仍然保留Spring Boot MVC自定义设置,可以声明WebMvcRegistrations类型的bean,并使用它来提供这些组件的自定义实例。
If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.
#如果您想完全控制springmvc,您可以添加自己的@Configuration,并用@EnableWebMvc注释,或者也可以添加自己的@Configuration annotated delegatingwebmvc配置,如@EnableWebMvc的Javadoc中所述。
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.
1.ContentNegotiatingViewResolver 内容协商视图解析器
翻译:
Content:内容
Negotiating:谈判;协商
ViewResolver:视图分析器
在学习SpringMVC时,我们用到了ViewResolver(视图解析器):即根据方法的返回值取得视图对象(View),然后由视图对象决定如何渲染(转发,重定向)。
查看源码:找到WebMvcAutoConfiguration
类,在其内部即可找到返回ContentNegotiatingViewResolver
的viewResolver()方法
我们可以点进这类看看!找到对应的解析视图的代码:
点击getCandidateViews
进去看,找到它是怎么获得候选的视图的:
- 得出结论:ContentNegotiatingViewResolver 这个视图解析器就是用来组合所有的视图解析器的
我们再去研究下他的组合逻辑,看到有个属性viewResolvers,看看它是在哪里进行赋值的.
protected void initServletContext(ServletContext servletContext) {
Collection<ViewResolver> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(this.obtainApplicationContext(), ViewResolver.class).values();
ViewResolver viewResolver;
if (this.viewResolvers == null) {
this.viewResolvers = new ArrayList(matchingBeans.size());
Iterator var3 = matchingBeans.iterator();
while(var3.hasNext()) {
viewResolver = (ViewResolver)var3.next();
if (this != viewResolver) {
this.viewResolvers.add(viewResolver);
}
}
......
既然它是在容器中去找视图解析器,我们就可以给容器中添加一个视图解析器。ContentNegotiatingViewResolver
可以帮我们组合。
1、在主程序中写一个视图解析器来试试:
package com.example.view;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import java.util.Locale;
@SpringBootApplication
public class ViewApplication {
public static void main(String[] args) {
SpringApplication.run(ViewApplication.class, args);
}
@Bean //放到bean中
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
//我们写一个静态内部类,视图解析器就需要实现ViewResolver接口
private static class MyViewResolver implements ViewResolver {
@Override
public View resolveViewName(String s, Locale locale) throws Exception {
return null;
}
}
}
2、怎么看我们自己写的视图解析器有没有起作用呢?
在application.properties
文件中添加debug=true
启动项目,在Positive matches:
中找到了自己定义的视图解析器!
如果想要使用自己定制化的东西,我们只需要给容器中添加这个组件,剩下的事情SpringBoot就会帮我们做了!
二、SpringBoot:转换器和格式化器
1.找到格式化转换器:
@Bean
public FormattingConversionService mvcConversionService() {
Format format = this.mvcProperties.getFormat();
WebConversionService conversionService = new WebConversionService((new DateTimeFormatters()).dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
this.addFormatters(conversionService);
return conversionService;
}
点击getFormat()
的源码,看到:
在WebMvcProperties
类中看到:
其中,class Format 源码:
在WebMvcProperties
类中,我们可以看到:properties for Spring MVC.
可以看到在我们的Properties文件中,我们可以进行自动配置它!
总结:
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的;
如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来!
- 扩展使用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.
- 全面接管SpringMVC,官方文档如下:(不推荐)
If you want to take complete control of Spring MVC
you can add your own @Configuration annotated with @EnableWebMvc.
全面接管即:SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己去配置!
只需在我们的配置类中要加一个@EnableWebMvc。访问如下:
- 开发中,不推荐使用全面接管SpringMVC
思考问题?为什么加了一个注解,自动配置就失效了!
1.看EnableWebMvc
的源码发现,它导入一个类这里发现它是导入了一个类:@Import({DelegatingWebMvcConfiguration.class})
2.DelegatingWebMvcConfiguration 继承 WebMvcConfigurationSupport
3.我们来回顾一下Webmvc自动配置类
三、SpringBoot:静态资源处理
SpringBoot最大的特点就是自动装配,开发步骤简单,程序员可以专注编写业务代码,不需要考虑以前那样一大堆的配置了。
在我们项目的中有许多的静态资源,比如css,js等文件,以前如果是一个web应用,我们的main下会有一个webapp,所有web资源在这里面的。在SpringBoot中又是如何应用的呢?
下面介绍一下,SpringBoot静态资源映射规则:
SpringBoot中,SpringMVC的web配置都在WebMvcAutoConfiguration
这个配置类里面,可以去看看 WebMvcAutoConfigurationAdapter
:
另外,可以看到addResourceHandlers()方法:添加资源处理
啥是 /webjars/** ,为啥都需要去 classpath:/META-INF/resources/webjars/ 找对应的资源?
Webjars本质就是以jar包的方式引入我们的静态资源 , 我们以前要导入一个静态资源文件,直接导入即可。
使用SpringBoot需要使用Webjars,网站地址。
比如:
要使用jQuery,我们只要要引入jQuery对应版本的pom依赖即可!
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.6.0</version>
</dependency>
导入完毕,查看webjars目录结构,并访问Jquery.js文件
- 只要是静态资源,SpringBoot就会去对应的路径寻找资源,我们这里访问:http://localhost:8083/webjars/jquery/3.6.0/jquery.js
- 项目中如何使用自己的静态资源?
我们去找staticPathPattern
/**
* Path pattern used for static resources.
*/
private String staticPathPattern = "/**";
发现第二种映射规则 :/** , 访问当前的项目任意资源,它会去找 resourceProperties 这个类:
再进入 Resources 类中,发现:
ResourceProperties
可以设置和我们静态资源有关的参数;这里面指向了它会去寻找资源的文件夹,以下四个目录存放的静态资源可以被我们识别:
"classpath:/META-INF/resources/"
"classpath:/resources/"
"classpath:/static/"
"classpath:/public/"
- 自定义静态资源路径
我们也可以自己通过配置文件来指定一下,哪些文件夹是需要我们放静态资源文件的,在application.properties或者application.yaml中配置:
spring.web.resources.static-locations=classpath:/coding,classpath:zhou/
一旦自己定义了静态文件夹的路径,原来的自动配置就都会失效!
-
首页的处理
WelcomePageHandlerMapping
点进去继续看:
欢迎页,静态资源文件夹下的所有 index.html 页面;被 /** 映射。
比如我访问: http://localhost:8083/ ,就会找静态资源文件夹下的 index.html