文章目录
- 一、SpringBoot对静态资源的映射规则
- 1.1 /webjars/映射
- 1.2 staticPathPattern映射
- 1.3 欢迎页映射
- 1.4 标题图标映射
- 二、使用Thymeleaf模板引擎
- 2.1 Thymeleaf介绍
- 2.2 语法规则
- 2.3 表达式
- 三、SpringMVC自动配置
- 3.1 SpringMVC auto-configuration
- 3.2 修改SpringBoot的默认配置
- 3.3 扩展SpringMVC
- 3.4 全面接管SpringMVC
使用SpringBoot
进行web开发更加简单:
- 在创建SpringBoot应用时,选中我们需要的模块。
- SpringBoot已经默认将许多场景配置好了,只需要在配置文件中指定少量的配置就可以运行了。
- 剩下的就是自己编写业务代码。
想要将SpringBoot使用的很清楚,就需要搞清楚每一个组件SpringBoot
是帮我们怎么配置的,用到了配置类的哪些信息,如何修改等。
xxxAutoConfiguration
:帮我们给容器中自动配置组件。xxxxProperties
:配置类来封装配置文件的内容。
一、SpringBoot对静态资源的映射规则
SpringBoot中关于SpringMVC的相关配置都在WebMvcAutoConfiguration
中。
WebMvcAutoConfiguration源码:
public class WebMvcAutoConfiguration {
...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjarsfavicon.ico
都是在静态资源文件下找;
- 即将标题图标
可以手动在application.properties
中配置静态资源文件夹的路径:
spring.resources.static-locations=classpath:/mydisk1/,classpath:/mydisk2/
二、使用Thymeleaf模板引擎
2.1 Thymeleaf介绍
模板引擎的思想:页面模板Template中有一些动态的值需要使用到表达式,这些表达式来自我们组装的数据Data。将页面模板Template
、组装数据Data
交给模板引擎Thymeleaf
后,模板引擎按照组装数据将页面模板中的表达式解析并填充进而写出。
Thymeleaf
是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP
,Velocity
,FreeMaker
等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面
,而不需要启动整个Web应用。
Spring Boot推荐使用Thymeleaf
、Freemarker
等后现代的模板引擎技术;一但导入相关依赖,会自动配置ThymeleafAutoConfiguration
、FreeMarkerAutoConfiguration
。
引入Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
自动渲染
ThymeleafProperties源码:
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
//前缀
public static final String DEFAULT_PREFIX = "classpath:/templates/";
//后缀
public static final String DEFAULT_SUFFIX = ".html";
只要我们把HTML页面放在classpath:/templates/
,thymeleaf
就能自动渲染。
2.2 语法规则
首先,导入thymeleaf
的名称空间:xmlns:th="http://www.thymeleaf.org"
。
(1)th:text:改变当前元素里面的文本内容。
- Controller
@RequestMapping("/success")
public String success(Map<String,Object> map){
map.put("hello","你好");
return "success";
}
- success页面
<body>
<h1>成功1</h1>
<div th:text="${hello}">这是欢迎信息</div>
</body>
- th:text取值成功
除了使用th:text
,还可以使用th:任意html属性,来替换原生属性的值。可以在 Thymeleaf官网 查看到属性的优先级。
2.3 表达式
可以在 Thymeleaf官网 的Standard Expression Syntax
一栏查看表达式语法。
${…}
:获取变量值
1)、获取对象的属性、调用方法
2)、使用内置的基本对象:
#ctx : the context object.
#vars: the context variables.
#vars: the context variables.
#locale : the context locale.
#request : (only in Web Contexts) the HttpServletRequest object.
#response : (only in Web Contexts) the HttpServletResponse object.
#session : (only in Web Contexts) the HttpSession object.
#servletContext : (only in Web Contexts) the ServletContext object.
例:${session.foo}
3)、内置的一些工具对象:
#execInfo : information about the template being processed.
#messages : methods for obtaining externalized messages inside variables expressions, in the
same way as they would be obtained using #{…} syntax.
#uris : methods for escaping parts of URLs/URIs
#conversions : methods for executing the configured conversion service (if any).
#dates : methods for java.util.Date objects: formatting, component extraction, etc.
#calendars : analogous to #dates , but for java.util.Calendar objects.
#numbers : methods for formatting numeric objects.
#strings : methods for String objects: contains, startsWith, prepending/appending, etc.
#objects : methods for objects in general.
#bools : methods for boolean evaluation.
#arrays : methods for arrays.
#lists : methods for lists.
#sets : methods for sets.
#maps : methods for maps.
#aggregates : methods for creating aggregates on arrays or collections.
#ids : methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
*{…}
:选择表达式,当前对象/变量取值
*{…}和`${}`在功能上是一样,不过有了改进:
使用
<div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
替代↓
<div>
<p>Name: <span th:text="${session.userfirstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="${session.userlastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="${session.usernationality}">Saturn</span>.</p>
</div>
-
#{...}
:国际化消息 -
@{…}
:定义url链接
@{/order/process(execId=${execId},execType='FAST')}
~{…}
:片段引用表达式
<div th:insert="~{commons :: main}">...</div>
举例:
Controller控制器
@RequestMapping("/success")
public String success(Map<String,Object> map){
map.put("hello","<h1>你好</h1>");
map.put("users", Arrays.asList("张三","李四","王五"));
return "success";
}
前台页面
<body>
<h1>成功1</h1>
<!--th:text 将div中的文本内容设置为指定值-->
<div th:text="${hello}">转义</div>
<div th:utext="${hello}">不转义</div>
<hr/>
<!--th:each每次遍历都会生成当前这个标签-->
<h4 th:text="${user}" th:each="user:${users}"></h4>
<hr/>
<h4>
<span th:each="user:${users}">[[${user}]]</span>
</h4>
</body>
三、SpringMVC自动配置
3.1 SpringMVC auto-configuration
SpringMVC的自动配置可以参照SpringBoot官网第27节。
Spring Boot 自动配置好了SpringMVC,以下是SpringBoot对SpringMVC的默认配置:WebMvcAutoConfiguration
(1) 包含
ContentNegotiatingViewResolver
和BeanNameViewResolver
。
- ①自动配置了
ViewResolver
(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染or转发or重定向) - ②
ContentNegotiatingViewResolver
:组合所有的视图解析器,选择合适的视图解析器。 - ③定制:我们可以自己给容器中添加一个视图解析器,ContentNegotiatingViewResolver会自动的将其组合进来。
演示定制视图解析器:
@Bean
public ViewResolver myViewResolver(){
return new MyViewResolver();
}
private static class MyViewResolver implements ViewResolver{
@Override
public View resolveViewName(String s, Locale locale) throws Exception {
return null;
}
}
(2) 支持提供静态资源,包括对WebJars的支持。上文已经介绍过,这里不做赘述。
(3) 自动注册了
Converter
、GenericConverter
、Formatter
的beans.
-
Converter:类型转换器。
如果页面带来的数据和Bean中的属性一一对应,SpringMVC就会进行自动封装。但容易出现类型转换问题,如将String文本信息转换为Integer类型。 -
Formatter:格式化器。
如将页面带来的数据转换为Date类型,2017.12.17===Date。
自己添加的格式化转换器,放在容器中即可。
源码:
public class WebMvcAutoConfiguration {
...
@Override
public void addFormatters(FormatterRegistry registry) {
ApplicationConversionService.addBeans(registry, this.beanFactory);
}
...
}
(4) 配置了消息转换器
HttpMessageConverters
- HttpMessageConverters:消息转换器,SpringMVC用来转换Http请求和响应的。
- HttpMessageConverters是从容器中确定,底层仍是获取所有的HttpMessageConverter,所以也可以将自己的组件注册到容器(@Bean,@Component)。
(5)
MessageCodesResolver
:定义错误代码生成规则
(6)
ConfigurableWebBindingInitializer
:定义错误代码生成规则
可以手动配置一个ConfigurableWebBindingInitializer
来替换默认的,添加到容器中。
ConfigurableWebBindingInitializer
可以初始化数据绑定器WebDataBinder
。
请求数据封装为JavaBean时需要用到WebDataBinder
(其中涉及类型转换、格式化等)。
除了上面SpringMVC的几种自动配置,web场景还有很多的自动配置在
org.springframework.boot.autoconfigure.web
包中。
3.2 修改SpringBoot的默认配置
- SpringBoot在自动配置组件的时候,先看容器中有没有用户自己配置的(
@Bean
、@Component
)如果有就用用户配置的;如果没有,才自动配置;如果有些组件可以有多个(如ViewResolver
)就会将用户配置的和自己默认的组合起来; 扩展配置
:在SpringBoot中会有非常多的xxxConfigurer
帮助我们进行扩展配置。定制配置
:在SpringBoot中会有很多的xxxCustomizer
帮助我们进行定制配置。
3.3 扩展SpringMVC
实际开发过程中,仅靠SpringBoot的这些自动配置是不够用的。假设现在需要扩展下面两个功能。
<mvc:view-controller path="/hello" view-name="success"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean></bean>
</mvc:interceptor>
</mvc:interceptors>
编写一个继承了WebMvcConfigurationSupport
的配置类(@Configuration
),不要标注@EnableWebMvc
注解。既保留了所有的自动配置,也能用我们扩展的配置。
@Configuration
public class MyMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
//功能:浏览器发送 /hello请求,也来到 success
registry.addViewController("/hello").setViewName("success");
}
}
扩展原理
- ①
WebMvcAutoConfiguration
是SpringMVC的自动配置类 - ②在做其他自动配置时会导入
@Import(EnableWebMvcConfiguration.class)
。
即容器中所有的WebMvcConfigurer
会一起起作用。
源码:
public class WebMvcAutoConfiguration {
...
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {....}
...
}
EnableWebMvcConfiguration 继承了父类DelegatingWebMvcConfiguration
------------------------------------------------------------------------------------------
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
...
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
//从容器中获取所有的WebMvcConfigurer,添加到configurers中
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
//一个参考实现;将所有的WebMvcConfigurer相关的配合都调用一次,
//@Override
//public void addViewControllers(ViewControllerRegistry registry) {
// for (WebMvcConfigurer delegate : this.delegates) {
// delegate.addViewControllers(registry);
// }
//}
}
}
...
}
- ③扩展配置类也会被调用。
效果:SpringMVC的自动配置和我们的扩展配置都会起作用
3.4 全面接管SpringMVC
只需要在配置类中添加@EnableWebMvc
,就可以全面接管SpringMVC。使所有的SpringMVC的自动配置都失效,所有都是我们自己配置。
为什么使用了@EnableWebMvc
后,自动配置就失效了?
源码:
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
-------------------------------------------------------------------
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
...
}
WebMvcAutoConfiguration
类上有一个@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
注解,该注解作用是:当容器中没有WebMvcConfigurationSupport
组件的时候,自动配置才生效。
@EnableWebMvc
注解导入了DelegatingWebMvcConfiguration
组件,而DelegatingWebMvcConfiguration
组件继承了WebMvcConfigurationSupport
。
导入的WebMvcConfigurationSupport
只是SpringMVC最基本的功能。