SpringBoot系列文章
文章目录
- 1. 简介
- 2. SpringBoot对静态资源的映射规则
- 2.1 访问webjars资源
- 2.2 访问自己的静态资源
- 2.3 欢迎页映射
- 2.4 网站图标映射
- 3. 模板引擎
- 3.1 引入模板引擎thymeleaf
- 3.2 thymeleaf 的使用
- 3.3 thymeleaf 语法规则
- 4. SpringMVC配置
- 4.1 视图解析器
- 4.2 转换器、格式化器
- 4.3 HttpMessageConverters
- 4.4 MessageCodesResolver
- 4.5 ConfigurableWebBindingInitializer
- 5. 扩展SpringMVC
- 5.1 原理
- 6. 全面接管SpringMVC
- 6.1 原理
- 7. 如何修改SpringBoot的默认配置
1. 简介
使用SpringBoot进行Web开发的大致流程
- 创建SpringBoot应用,选中我们需要的模块
- SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
- 编写业务代码
2. SpringBoot对静态资源的映射规则
WebMvcAutoConfiguration
类的addResourceHandlers
方法:(添加资源映射)
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
//如果请求是/webjars/**,将请求与classpath:/META-INF/resources/webjars/进行映射,setCachePeriod方法,
//设置缓存时间
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
//将/**请求与getStaticLocations()获取的资源进行映射
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
2.1 访问webjars资源
所有/webjars/**
的请求,SpringBoot都去classpath:/META-INF/resources/webjars/
下找资源(映射)
webjars:以jar包的形式引入的静态资源,前端框架可以去webars官网去找对应的maven依赖。
例如:添加jquery的webjars
访问地址对应就是:http://localhost:8080/webjars/jquery/3.4.1/jquery.js
2.2 访问自己的静态资源
/**
,访问当前项目的任何资源,如果没有controller
处理,springBoot默认去classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/
寻找相应资源。这一点,可以根据addResourceHandlers
中的getStaticLocations()
源码中看出。
getStaticLocations()
@ConfigurationProperties( //说明可以在配置文件中配置相关参数
prefix = "spring.resources",
ignoreUnknownFields = false
)
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private final ResourceProperties.Chain chain;
private final ResourceProperties.Cache cache;
public ResourceProperties() {
this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
this.addMappings = true;
this.chain = new ResourceProperties.Chain();
this.cache = new ResourceProperties.Cache();
}
public String[] getStaticLocations() {
return this.staticLocations;
}
上图中添加的映射访问路径staticPathPattern
值是/**
,对应的资源文件夹就是上面配置类ResourceProperties
中的CLASSPATH_RESOURCE_LOCATIONS
数组中的文件夹:
数组中的值 | 对应项目中的位置 |
classpath:/META-INF/resources/ | src/main/resources/META-INF/resources/ |
classpath:/resources/ | src/main/resources/resources/ |
classpath:/static/ | src/main/resources/static/ |
classpath:/public/ | src/main/resources/public/ |
classpath 等价于 main/java + main/resources + 第三方jar包的根目录,另外,当SpringBoot检索资源时,“/”就代表了从根路径搜索,而搜索的范围包括:main/java、main/resources、第三方jar包的根目录。
如果访问localhost:8080/abc,SpringBoot就会去这些静态资源文件夹中找abc的文件,也就是说,当请求地址是/**类型的,如果没有处理,SpringBoot默认会去上面的那些文件夹中寻找资源。
2.3 欢迎页映射
location就是静态资源路径,所以欢迎页的页面就是上面静态资源文件夹下的index.html,被/**映射,因此直接访问项目就是访问欢迎页。
2.4 网站图标映射
所有的 favicon.ico 都是在静态资源文件下找
可以在配置文件中使用spring.resources.staticLocations,来改变静态资源文件夹的路径。
3. 模板引擎
常见的模板引擎有JSP、Velocity、Freemarker、Thymeleaf
SpringBoot推荐使用Thymeleaf;
3.1 引入模板引擎thymeleaf
<!--引入模板引擎thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3.2 thymeleaf 的使用
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
...
只要我们把HTML页面放在classpath:/templates/
,thymeleaf就能自动渲染
使用:
- 在src/main/resources/temeplates下创建html文件,导入thymeleaf的名称空间(可以自动提示)
<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 在Controller层设置数据
@Controller
public class HelloController {
@RequestMapping("/success")
public String success(Model model){
model.addAttribute("title","success");
model.addAttribute("info","this is thymeleaf");
return "t";
}
}
- 使用thymeleaf语法(t.html)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${title}"></h1>
<span th:text="${info}">这里的文本将会被覆盖</span>
</body>
</html>
3.3 thymeleaf 语法规则
- th:text :改变当前元素(标签)里面的文本内容,如果有特殊字符,不会转译,直接输出,用在标签里面。
- th:utext: 也是改变当前标签里面的文本内容,如果有特殊字符,会转译,不会直接输出,用在标签里面。
- th:任意html属性,替换原生属性的值
具体用法可以参考官方文档attribute-precedence
表达式:
- ${…} 获取变量值,OGNL
- 获取对象的属性、调用方法
- 使用内置的基本对象和工具对象
- {…} 选择表达式,和${}功能一样,不一样的是可以用代替对象
- #{…}:获取国际化内容
- @{…}:定义URL
具体用法可以 参考官方文档Standard Expression
4. SpringMVC配置
Spring Boot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。
想要看SpringBoot中对SpringMvc的默认配置,可以查看官方文档,也可以看SpringMVC的自动配置类org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
以下是springboot对SpringMVC的默认配置(官方文档中的介绍)
- 包含ContentNegotiatingViewResolver和BeanNameViewResolver。–> 视图解析器
- 支持服务静态资源,包括对WebJars的支持。–> 静态资源文件夹路径
- 自动注册Converter,GenericConverter和Formatterbeans。–> 转换器,格式化器
- 支持HttpMessageConverters)。–> SpringMVC用来转换Http请求和响应的;User—Json;
- 自动注册MessageCodesResolver)。–> 定义错误代码生成规则
- 静态index.html支持。–> 静态首页访问
- 定制Favicon支持。–> 网站图标
- 自动使用ConfigurableWebBindingInitializerbean。
4.1 视图解析器
视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发或重定向)
- 自动配置了ViewResolver,ContentNegotiatingViewResolver,组合所有的视图解析器
视图解析器从哪里来的?
所以我们可以自己给容器中添加一个视图解析器,ContentNegotiatingViewResolver会自动的将其组合进来
使用debug检验
4.2 转换器、格式化器
- Converter:转换器,比如页面中的发过来的消息都是String类型的,转换器可以转换成java类型。
- Formatter 格式化器; 比如将日期转换成Date类型,2017.12.17===Date;
@Bean
//在配置文件中配置日期格式化的规则,就会注册这个日期格式化组件
@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")
public Formatter<Date> dateFormatter() {
return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
}
自己添加的格式化器转换器,我们只需要放在容器中即可
public void addFormatters(FormatterRegistry registry) {
ApplicationConversionService.addBeans(registry, this.beanFactory);
}
4.3 HttpMessageConverters
- HttpMessageConverter:SpringMVC用来转换Http请求和响应的,比如将数据转换成json格式。
- HttpMessageConverters 是从容器中确定,获取所有的HttpMessageConverter;
自己给容器中添加HttpMessageConverter,只需要将自己的组件注册容器中(@Bean,@Component)
4.4 MessageCodesResolver
定义错误代码生成规则
4.5 ConfigurableWebBindingInitializer
初始化WebDataBinder(Web数据绑定器:将请求数据与javaBean绑定),我们可以配置一个ConfigurableWebBindingInitializer来替换默认的(添加到容器)
上面是SpringBoot中对SpringMVC的自动配置,还有其他的web自动配置,可以在org.springframework.boot.autoconfigure.web
下看SpringBoot对web的其他自动配置。
5. 扩展SpringMVC
如果您想保留 Spring Boot MVC 的功能,并且需要添加其他 MVC 配置(拦截器,格式化程序和视图控制器等),可以添加自己的 WebMvcConfigurer 类型的 @Configuration 类,但不能带 @EnableWebMvc 注解。如果您想自定义 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或者 ExceptionHandlerExceptionResolver 实例,可以声明一个 WebMvcRegistrationsAdapter 实例来提供这些组件。
如果您想完全掌控 Spring MVC,可以添加自定义注解了 @EnableWebMvc 的 @Configuration 配置类。
以前在SpringMVC中,可以配置
<mvc:view-controller path="/hello" view-name="success"/>
当收到hello请求时,返回success页面。
现在,编写一个配置类(使用@Configuration标注),是WebMvcConfigurer类型,不能标注@EnableWebMvc
//使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能 ,实现WebMvcConfigurer接口
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//收到hi请求,返回t页面,也就是将t.html交给模板引擎渲染
registry.addViewController("/hi").setViewName("t");
}
}
5.1 原理
我们知道WebMvcAutoConfiguration是SpringMVC的自动配置类
下面这个类是WebMvcAutoConfiguration
中的一个内部类
看一下@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
中的这个类,这个类依旧是WebMvcAutoConfiguration中的一个内部类
重点看一下这个类继承的父类DelegatingWebMvcConfiguration
@Configuration(
proxyBeanMethods = false
)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
public DelegatingWebMvcConfiguration() {
}
@Autowired(required = false) //使用@Autowired,默认从容器中获取configurers
//将容器中所有的WebMvcConfigurer存到this.configurers中
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
...
/* 拿这个类中的addViewControllers方法举例
this.configurers:也是WebMvcConfigurer接口的一个实现类
*/
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
}
this.configurers.addViewControllers(registry),遍历所有的WebMvcConfigurer,并且都执行addViewControllers(registry)
public void addViewControllers(ViewControllerRegistry registry) {
Iterator var2 = this.delegates.iterator();
while(var2.hasNext()) {
WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
delegate.addViewControllers(registry);
}
}
delegate.addViewControllers(registry),调用WebMvcConfigurer接口中的 addViewControllers方法,也就是调用WebMvcConfigurer实现类的方法,实现扩展功能。
default void addViewControllers(ViewControllerRegistry registry) {
}
容器中所有的WebMvcConfigurer
都会一起起作用;
我们的配置类也会被调用;
效果:SpringMVC的自动配置和我们的扩展配置都会起作用;
6. 全面接管SpringMVC
我们只需要在配置类中添加 @EnableWebMvc
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer
6.1 原理
为什么使用了@EnableWebMvc
注解之后,springMVC的自动配置就失效了
我们看一下EnableWebMvc注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//主要是注册了DelegatingWebMvcConfiguration类
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
重点在于 @Import({DelegatingWebMvcConfiguration.class})
DelegatingWebMvcConfiguration
是WebMvcConfigurationSupport
的子类
我们再来看一下springmvc的自动配置类WebMvcAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
//重点是这个注解,只有容器中没有WebMvcConfigurationSupport类型的bean时,
//才会将WebMvcAutoConfiguration 注册到容器中,自动配置才会生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
...
}
@EnableWebMvc
将WebMvcConfigurationSupport
组件导入进来,导入的WebMvcConfigurationSupport只提供SpringMVC最基本的功能。
7. 如何修改SpringBoot的默认配置
SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component),如果有,就使用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(如ViewResolver),SpringBoot会将用户配置的和自己默认的组合起来使用;
- 在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置
- 在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置