步骤:
1、整合web场景(导入web场景启动器)
2、引入了 autoconfigure功能
3、@EnableAutoConfiguration注解使用@Import(AutoConfigurationImportSelector.class)批量导入组件
4、加载 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中配置的所有组件
5、所有自动配置类如下:
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration
====以下是响应式web场景和现在的没关系======
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration
================以上没关系=================
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
6、这些配置类绑定了配置文件的一堆配置项
● 1、SpringMVC的所有配置===========》 以spring.mvc开头
● 2、Web场景通用配置 ===========》以spring.web开头
● 3、文件上传配置 ============》以spring.servlet.multipart开头
● 4、服务器的配置 ==============》以server开头: 比如:编码方式
默认配置:(默认配置的springmvc的特性)
1. 包含了 ContentNegotiatingViewResolver 和 BeanNameViewResolver 组件,方便视图解析
2. 默认的静态资源处理机制: 静态资源放在 static 文件夹下即可直接访问
3. 自动注册了(类型转换器和格式化器) Converter,GenericConverter,Formatter组件,适配常见数据类型转换和格式化需求
格式化器: 写在文件中的内容统一是字符,springboot在给属性赋值时要将这些字符转化为对应的类型
4. 支持 HttpMessageConverters,可以方便返回json等数据类型
5. 注册 MessageCodesResolver,方便国际化及错误消息处理
6. 支持 静态 index.html
7. 自动使用ConfigurableWebBindingInitializer(web数据绑定工作),实现消息处理、数据绑定、类型转化、数据校验等功能
重要:
● 如果想保持 boot mvc 的默认配置,并且自定义更多的 mvc 配置,如:interceptors, formatters, view controllers 等。可以使用@Configuration注解添加一个 WebMvcConfigurer 类型的配置类,并不要标注 @EnableWebMvc
● 如果想保持 boot mvc 的默认配置,但要自定义核心组件实例,比如:RequestMappingHandlerMapping,,RequestMappingHandlerAdapter, 或ExceptionHandlerExceptionResolver,给容器中放一个 WebMvcRegistrations 组件即可
● 如果想全面接管 Spring MVC,@Configuration 标注一个配置类,并加上 @EnableWebMvc注解,实现 WebMvcConfigurer 接口(ssm中springmvc的步骤)
三种方式
方式 |
用法 |
效果 |
全自动 |
直接编写控制器逻辑 |
全部使用自动配置默认效果 |
手自一体(常用) |
@Configuration + 配置WebMvcConfigurer(实现它)+配置 WebMvcRegistrations 不要标注@EnableWebMvc |
保留自动配置效果手动设置部分功能定义MVC底层组件 |
全手动 |
@Configuration + 配置WebMvcConfigurer(实现它) 标注@EnableWebMvc |
禁用自动配置效果全手动设置 |
总结:
给容器中写一个配置类@Configuration实现 WebMvcConfigurer但是不要标注 @EnableWebMvc注解,实现手自一体的效果。
注意:@EnableWebMvc 作用:添加handlerMapping与handlerAdapter,并给handlerAdapter添加json处理器
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class }) //在这些自动配置之后才配置
@ConditionalOnWebApplication(type = Type.SERVLET) //如果是web应用就生效,web应用必须是类型SERVLET、REACTIVE 响应式web
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) //容器中没有这个Bean,才生效。默认就是没有
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)//优先级
@ImportRuntimeHints(WebResourcesRuntimeHints.class)
public class WebMvcAutoConfiguration {
}
1. 放了两个Filter:
a. HiddenHttpMethodFilter;页面表单提交Restful请求(GET、POST、PUT、DELETE)
b. FormContentFilter: 表单内容Filter,GET(数据放URL后面)、POST(数据放请求体)请求可以携带数据,PUT、DELETE 的请求体数据会被忽略(加上此filter让其不被忽略)
2. 给容器中放了WebMvcConfigurer组件;给SpringMVC添加各种定制功能
WebMvcConfigurer
提供了springmvc底层的所有组件入口
有一个参数解析器(让方法中的参数准确的从请求中获取传过来的值)
有一个格式化器(让配置文件中的字符转换为对应类型--------读取配置文件给属性赋值时)
WebMvcAutoConfiguration里的一个内部类:
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class) //额外导入了其他配置
@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware{
}
a. 所有的功能最终会和配置文件进行绑定
b. WebMvcProperties: spring.mvc配置文件
c. WebProperties: spring.web配置文件
静态资源规则源码
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
//1、
addResourceHandler(registry, this.mvcProperties.getWebjarsPathPattern(),
"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);
}
});
}
1. 规则一:访问: /webjars/**路径就去 classpath:/META-INF/resources/webjars/下找资源.
2. 规则二:访问: /**路径就去 静态资源默认的四个位置找资源
a. classpath:/META-INF/resources/
b. classpath:/resources/
c. classpath:/static/
d. classpath:/public/
3. 规则三:静态资源默认都有缓存规则的设置
a. 所有缓存的设置,直接通过配置文件: spring.web
b. cachePeriod: 缓存周期; 多久不用找服务器要新的。 默认没有,以s为单位
c. cacheControl: HTTP缓存控制;
d. useLastModified:是否使用最后一次修改。配合HTTP Cache规则
如果浏览器访问了一个静态资源 index.js,如果服务这个资源没有发生变化(让服务器返回修改时间,如果和上一次访问的资源的修修改时间一致),下次访问的时候就可以直接让浏览器用自己缓存中的东西,而不用给服务器发请求。
静态资源映射规则在 WebMvcAutoConfiguration 中进行了定义:
1. /webjars/** 的所有路径 资源都在 classpath:/META-INF/resources/webjars/
任何以 /webjars开头的请求都会自动去 classpath:/META-INF/resources/webjars/下找
classpath:/META-INF/resources/webjars/是规范定义的存储静态资源的标准位置,当这些库被打包成jar文件时它们的静态资源就放在这个路径下。
2. /** 的所有路径 资源都在 classpath:/META-INF/resources/、classpath:/resources/、classpath:/static/、classpath:/public/
3. 所有静态资源都定义了缓存规则。【浏览器访问过一次,就会缓存一段时间】,但此功能参数无默认值
a. period: 缓存间隔。 默认 0S;
b. cacheControl:缓存控制。 默认无;
c. useLastModified:是否使用lastModified头。 默认 false;
如前面所述
1. 所有静态资源都定义了缓存规则。【浏览器访问过一次,就会缓存一段时间】,但此功能参数无默认值
a. period: 缓存间隔。 默认 0S;
b. cacheControl:缓存控制。 默认无;
c. useLastModified:是否使用lastModified头。 默认 false;
欢迎页
欢迎页规则在 WebMvcAutoConfiguration 中进行了定义:
1. 在静态资源目录下找 index.html
2. 没有就在 templates下找index模板页
欢迎页的源码分析
EnableWebMvcConfiguration (是WebMvcAutoConfiguration 的内部类)源码
//SpringBoot 给容器中放 WebMvcConfigurationSupport(DelegatingWebMvcConfiguration会继承它) 组件。
//我们如果自己放了 WebMvcConfigurationSupport 组件,Boot的WebMvcAutoConfiguration都会失效。
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware
{
}
1. HandlerMapping: 根据请求路径 /a 找那个handler能处理请求
作用图:
a. WelcomePageHandlerMapping:
ⅰ. 访问 /**(静态资源)路径下的所有请求,都在以前四个静态资源路径下找,欢迎页也一样
ⅱ. 找index.html:只要静态资源的位置有一个 index.html页面,项目启动默认访问
在静态资源目录下找 favicon.ico(将一个名称为favicon.ico的图片放在静态资源路径下,那么我们浏览器的页面小图标就会变为该图片)
spring.application.name=boot3-04-web
#spring.web
#1.配置国际化的区域信息
#2.配置静态资源策略
#开启静态资源映射规则
spring.web.resources.add-mappings=true
#设置缓存
spring.web.resources.cache.period=3600
#缓存的详细合并项控制,覆盖period配置
#浏览器第一次请求服务器,服务器告诉浏览器此资源缓存7200秒,7200秒内所有此资源的访问不用发给服务器请求(使用本地的),7200秒后发请求给服务器
spring.web.resources.cache.cachecontrol.max-age=7200
#使用资源last-modified(默认是true)--最后一次修改时间,来对比服务器和浏览器的资源是否相同没有变化,相同:返回304
spring.web.resources.cache.use-last-modified=true
静态资源访问前缀路径=========================》以spring.mvc:开头
● 静态资源目录============================》以spring.web:开头
● 静态资源缓存策略============================》以spring.web:开头
#设置共享缓存
spring.web.resources.cache.cachecontrol.cache-public=true
#重新设置静态资源文件夹的默认位置
spring.web.resources.static-locations=classpath:/a/,classpath:/b/
#spring.mvc
#1 自定义webjars路径前缀
spring.mvc.webjars-path-pattern=/wj/**
#2 自定义静态资源访问路径前缀(默认是/**)
#所有的静态资源都加一个static前缀(访问static下的路径,就会去a或b文件夹中找)
spring.mvc.static-path-pattern=/static/**
失败
成功
● 容器中只要有一个 WebMvcConfigurer 组件。配置的底层行为都会生效
● 加@EnableWebMvc //禁用boot的默认配置
手自一体模式
方式一
@Configuration//这是一个配置类
public class MyConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//保留原来配置
WebMvcConfigurer.super.addResourceHandlers(registry);
//自己写
/**
* 相当与
* spring.web.resources.static-locations=classpath:/a/,classpath:/b/
* spring.mvc.static-path-pattern=/static/**
* spring.web.resources.cache.cachecontrol.max-age=7200
*/
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/a/","classpath:/b/")//访问static下的路径,就会去a或b文件夹中找
.setCacheControl(CacheControl.maxAge(7200, TimeUnit.SECONDS));
}
}
方式二
@Configuration //这是一个配置类,给容器中放一个 WebMvcConfigurer 组件,就能自定义底层
public class MyConfig /*implements WebMvcConfigurer*/ {
@Bean
public WebMvcConfigurer webMvcConfigurer(){
return new WebMvcConfigurer() {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/a/", "classpath:/b/")
.setCacheControl(CacheControl.maxAge(1180, TimeUnit.SECONDS));
}
};
}
}
1. WebMvcAutoConfiguration 是一个自动配置类,它里面有一个 EnableWebMvcConfiguration
2. EnableWebMvcConfiguration继承与 DelegatingWebMvcConfiguration,这两个都生效
3. DelegatingWebMvcConfiguration利用 DI 把容器中 所有 WebMvcConfigurer 注入进来
4. 别人调用 `DelegatingWebMvcConfiguration` 的方法配置底层规则,而它调用所有 WebMvcConfigurer的配置底层方法。(所以我们自己写的底层配置方法就得到了调用)
Ant 风格的路径模式语法具有以下规则:
● *:表示任意数量的字符。
● ?:表示任意一个字符。
● **:表示任意数量的目录。
● {}:表示一个命名的模式占位符。
● []:表示字符集合,例如[a-z]表示小写字母。
例如:
● *.html 匹配任意名称,扩展名为.html的文件。
● /folder1/*/*.java 匹配在folder1目录下的任意两级目录下的.java文件。
● /folder2/**/*.jsp 匹配在folder2目录下任意目录深度的.jsp文件。
● /{type}/{id}.html 匹配任意文件名为{id}.html,在任意命名的{type}目录下的文件。
注意:Ant 风格的路径模式语法中的特殊字符需要转义,如:
● 要匹配文件路径中的星号,则需要转义为\\*。
● 要匹配文件路径中的问号,则需要转义为\\?。
● PathPatternParser 在 jmh 基准测试下,有 6~8 倍吞吐量提升,降低 30%~40%空间分配率
● PathPatternParser 兼容 AntPathMatcher语法,并支持更多类型的路径模式
● PathPatternParser "**" 多段匹配的支持仅允许在模式末尾使用
springboot默认使用新版的路径匹配器,不能匹配**在中间的情况,剩下的和antPathMatcher语法兼容
可以在配置文件中改变路径匹配策略:spring.mvc.pathmatch.matching-strategy=ant_path_matcher
总结:
● 使用默认的路径匹配规则,是由 PathPatternParser 提供的
● 如果路径中间需要有 **,替换成ant风格路径