主要内容
1. Thymeleaf
2. web定制
3. 容器定制
1. SpringBoot对静态资源的映射规则
1.1 创建SpringBoot项目
1). 创建SpringBoot应用,选中我们需要的模块
2). SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可
以运行起来
3). 自己编写业务代码
自动配置原理:我们要明白
每引入一个场景,SpringBoot帮我们配置了什么?能不能修改?能修改哪些配置?...
A: xxxxAutoConfiguration:帮我们给容器中自动配置组件
B:xxxxProperties:配置类来封装配置文件的内容。
1.2 SpringBoot对静态资源的映射规则:webjars
1).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("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
定义了映射规则:
A: 所有/webjars/**请求, 都去classpath:/META-INF/resources/webjars/找资源
webjars:以jar包的方式引入静态资源。
webjars:可以将jquery/bootstrap以maven依赖的方式交给我们。
比如导入jquery的坐标,我们就可以通过/webjars/**请求访问jquery包中的资源
B:这个jar包的项目结构,正好对应着SpringBoot对静态资源的映射规则
比如:localhost:8080/webjars/jquery/3.3.1/jquery.js这个请求,
都去classpath:/META-INF/resources/webjars/目录下找资源。
2). properties类用来封装配置文件的内容
我们可以修改默认的配置----来自这个类
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
}
1.2.1 测试一下
1.引入JQuery的依赖坐标:
<!--引入JQuery的webjar--> 在访问的时候只需要写webjars下面的资源名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version>
</dependency>
2.启动项目
3.请求localhost:8080/webjars/jquery/3.3.1/jquery.js
4.请求成功
1.3. 非webjars 静态资源怎么访问
另一种映射规则:/**
访问当前项目的任何资源,如果没人处理默认都去哪找?
把静态资源放到这些文件夹中,如果没人处理,都会到这些文件夹下找内容。
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":当前项目的根路径
resources是类路径的根目录,所以对应这几个文件夹:
访问时不加静态资源文件夹名:
localhost:8080/abc === 回去静态资源里面找abc资源
测试一下:http://localhost:8080/asserts/js/Chart.min.js
访问成功,注意Maven clean一下。
1.4 欢迎页的映射和favicon.ico小图标
1)
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
return welcomePageHandlerMapping;
}
欢迎页:静态资源文件夹下的所有index.html被 /** 映射
localhost:8080/
测试一下:localhost:8080
2)
所有的**/favicon.ico 都是在静态资源文件下找
1.4.1 手动配置映射规则
手动配置映射规则
这些静态资源资源映射配置都可以通过:staticLocation属性在主配置文件中进行配置
spring.resources.staticLocation=classpath:/xx/xx
2 Thymeleaf模版引擎
2.1 Thymeleaf概述
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模版引擎。类似JSP,Velocity,
FreeMaker等,它可以轻易的与Spring MVC等Web框架进行集成做为Web应用的模版引擎。与
其他模版引擎相比,Thymeleaf最大的特点是能够直接在浏览器中打开并正确显示模版页面,
而不需要启动整个web应用
SpringBoot推荐使用Thymeleaf,Freemarker等后现代的模版引擎技术;一旦导入相关
依赖,会自动配置ThymeleafAutoConfiguration,FreeMarkerutoConfiguration。
2.2 课程背景
在我们继续学习时,有一个非常严重的问题。
我们用的前端页面是html页面,如果是以前我们的开发习惯,是要将其转成JSP页面。
原因是为了方便使用其中的<c:foreach> <c:if>等逻辑代码。
但是我们现在用的是SpringBoot创建的项目默认打包方式是jar方式,不是web方式。
第二我们用的还是嵌入式的tomcat,所以是不支持JSP的。所以如果用纯静态页面方式开发
会带来非常大的麻烦。
所以SpringBoot推荐我们来使用模版引擎Thymeleaf。
2.3 模版引擎的作用
比如我们写一个页面模版,比如有些值是动态的,我们写一些表达式。这些值从哪来呢?
我们组装一些数据我们把这些数据得到。然后我们将模版和得到的数据交给模版引擎。
模版引擎按照数据将模版中的表达式解析,填充到指定的位置。然后把数据最终生成一个
正确的内容,然后写出去。
2.4 Thymeleaf模版引擎
2.4.1 Thymeleaf模版引擎的引入
引入Thymleaf:引入对应场景的starter
spring-boot-starter-thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
查看一下默认导入的Thymeleaf版本和响应的布局版本是否合适
布局功能的适配:
Thymeleaf3主程序 layout2以上版本
Thymeleaf2 larout1
通过spring-boot-starter-parent到spring-boot-dependencies我们发现自导配
置的Thymeleaf版本符合适配要求。
如果适配不满足,我们可以在<properties/>标签中修改。
<properties>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 -->
<!-- thymeleaf2 layout1-->
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>
2.4.2 Thymeleaf使用
1. 找到自动配置原理中的Properties对象
我们按照SpringBoot的自动配置原理看一下Thymeleaf的自动配置规则来使用。
在自动配置扩展包org/springframework/boot/autoconfigure里面能找到
thymeleaf的相关配置类 ThymeleafAutoConfiguration.java 。
自动配置类就是为IOC添加一些组建,而添加的这些组件,或者说返回值一般都是来自于
一个Properties对象。我们要找到这个Properties对象,里面就有Thymeleaf具体的配置
规则。找打ThymeleafProperties
2. 看一下Properties对象和配置文件绑定的具体规则
@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";
1. 默认的前后缀:视图解析器的规则
classpath:/templates/
.html"
只要我们把html页面放到classpath:/templates/,Thymeleaf就会帮我们自动
渲染我们的字符串返回值。
解析成:classpath:/templates/success.html页面
2. 测试一下:
A: 将页面放到类路径下的/templates
B: Controller代码
@RequestMapping("/success")
public String success(){
//解析成:classpath:/templates/success.html页面
return "success";
}
C: 访问请求:http://localhost:8080/success
3. Thymleaf使用起来就一句话:
只要我们把HTML页面放在classpath:/templates/目录下,Thymleaf就会自动帮
我们渲染。
2.4.3 Thymleaf的案例
1. Controller代码
//查出一些数据,在页面显示
@RequestMapping("/success")
public String success(Map<String, Object> map){
//数据默认会被放在请求域中:SpringBoot底层实现了,这里暂时不深究
map.put("hello","你好");
//解析成:classpath:/templates/success.html页面
return "success";
}
2. 在html页面导入Thymeleaf的语法空间
<html xmlns:th="http://www.thymeleaf.org">
3. success.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>success</title>
</head>
<body>
<h1>成功666!</h1>
<!--th:text="${hello}":将div里面的文本内容替换为${hello}-->
<div th:text="${hello}">这里是被替换的信息</div>
</body>
</html>
4. 分析一下:
Controller中的代码会将map.put("hello","你好");数据默认会被放在请求域中
具体实现是SpringBoot底层的,这里暂时不深究。
返回值是:return "success";会被SpringBoot解析成响应的资源:
classpath:/templates/success.html。
success.html代码:
展示一个<h1>成功666!</h1>
展示一个<div th:text="${hello}">这里是被替换的信息</div>
原本展示的静态页面展示的是:这里是被替换的信息
Thymeleaf改变当前元素里面的文本内容,Controller中map存的数据。
2.4.4 Thymleaf的语法规则
1) th:text:改变当前元素里面的文本内容
1. th: 替换元素标签的原生属性的值
演示:
<div id="div1" class="myDiv" th:id="${hello}" th:class="${hello}" th:text="${hello}">这里是被替换的信息</div>
将id="div1" class="myDiv"改成 id="你好" class="你好"
2. th的所有的语法
2) Thymeleaf表达式
Simple expressions:(5种表达式语法)
Variable Expressions: ${...}:${} 获取变量值,底层是OGNL
1).获取对象的属性,调用方法
调用方法:
${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}
2).使用内置的基本对象
#ctx : the context object. 上下文对象
#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.
用法示例在附录中:You can read the full reference of these objects in Appendix A.
手册P86
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).
具体演示在附录中:You can check what functions are offered by each of these utility objects in the Appendix B.
P95
Selection Variable Expressions: *{...}: *{} 变量的选择表达式
和${}在功能上是一样的,只不过有一个补充功能,配和th:object使用
示例:
<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 th:object="${session.user}">:取出user对象放到object中
<span th:text="*{firstName}">:*就代表着刚才取出的对象,等价
<span th:text="${session.user.firstName}">
Message Expressions: #{...}:*{}获取国际化内容的
Link URL Expressions: @{...}: @{}定义url链接的
<!-- 访问 'http://localhost:8080/gtvg/order/details?orderId=3'-->
<a href="details.html"
th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
Fragment Expressions: ~{...}: ~{} 片段引用的表达式
<div th:insert="~{commons :: main}">...</div>
Literals(字面量)
Text literals: 'one text' , 'Another one!' ,…
Number literals: 0 , 34 , 3.0 , 12.3 ,…
Boolean literals: true , false
Null literal: null
Literal tokens: one , sometext , main ,…
Text operations:(文本操作)
String concatenation: +
Literal substitutions: |The name is ${name}|
Arithmetic operations:(数学运算)
Binary operators: + , - , * , / , %
Minus sign (unary operator): -
Boolean operations:(布尔运算)
Binary operators: and , or
Boolean negation (unary operator): ! , not
Comparisons and equality:(比较运算)
Comparators: > , < , >= , <= ( gt , lt , ge , le )
Equality operators: == , != ( eq , ne )
Conditional operators:(条件判断)
If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else) --- 三元运算符
Default: (value) ?: (defaultvalue)
Special tokens:(特殊操作)
No-Operation: _
2.5 Thymleaf一个小案例
1. Controller代码:
@Controller
public class HelloWorld {
//查出一些数据,在页面显示
@RequestMapping("/success")
public String success(Map<String, Object> map){
//数据默认会被放在请求域中:SpringBoot底层实现了,这里暂时不深究
map.put("hello","<h1>你好</h1>");
map.put("users", Arrays.asList("zhangsan","lisi","wangwu"));
//解析成:classpath:/templates/success.html页面
return "success";
}
}
2.success.html代码
<body>
<h1>成功666!</h1>
<div id="div1" class="myDiv" th:id="${hello}" th:class="${hello}" th:text="${hello}">
这里是被替换的信息
</div>
<!--map.put("hello","<h1>你好</h1>");,th:text将标签中的空值替换成${hello}-->
<div th:text="${hello}"></div>
<div th:utext="${hello}"></div>
<hr/>
<!--遍历:map.put("users", Arrays.asList("zhangsan","lisi","wangwu"));-->
<!--th:each写在哪个标签上,每遍历一次都会生成一个标签-->
<h4 th:text="${user}" th:each="user:${users}"></h4>
<hr/>
<!--3个span标签-->
<h4>
<span th:each="user:${users}">
<!--行内表达式写法:[[...]] [(...)] : th:text th:utext-->
[[${user}]]
</span>
</h4>
</body>
3.测试结果
3 SpringMVC自动配置
SpringMVC的自动配置在:WebMvcAutoConfiguration这个类中
org.springframework.boot.autoconfigure.web:web的所有自动配置场景
27.1.1. Spring MVC自动配置
Spring Boot为Spring MVC提供的auto-configuration适用于大多数应用,并在Spring默认
功能上添加了以下特性:
以下是SpringBoot对SpringMVC的默认配置:
引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
自动配置了ViewResolver视图解析器bean,视图解析器根据方法的返回值得到视图
对象View,视图对象决定如何渲染(转发?重定向?...)
ContentNegotiatingViewResolver:组合所有的视图解析器
定制:我们可以给自己的容器中添加一个试图解析器,ContentNegotiatingViewResolver
会自动将其组合进来,放到IOC中。
对静态资源的支持,包括对WebJars的支持。
对静态index.html的支持。
对自定义Favicon的支持。
自动注册Converter,GenericConverter,Formatter beans。
Converter转换器
Formatter格式化器:日期和字符串
如果主配置文件中有:spring.mvc.date-format=xxxx,这个Formatter格式化器
Bean就会被加到IOC中:
@Bean
@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在文件中配置日期格式化的规则
public Formatter<Date> dateFormatter() {
return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化组件
}
自己添加的格式化转换器,我们只需要放在容器中即可。
对HttpMessageConverters的支持。
* HttpMessageConverters:SpringMVC中用来转换Http请求和响应的
比如:将user对象以json形式写出去。那么就需要一个HttpMessageConverters。
* HttpMessageConverters是从容器中确定,获取所有的HttpMessageConverters
* 自己给容器中添加HttpMessageConverters,只需要将自己的组件注册到容器中
(@Bean,@Component)
自动注册MessageCodeResolver。
定义错误代码生成规则。
自动使用ConfigurableWebBindingInitializer bean。
我们可以配置一个ConfigurableWebBindingInitializer来替换默认的(添加到容器中)
初始化WebDataBinder:web数据绑定器
web数据绑定:把请求数据绑定到JavaBean中。
如果保留Spring Boot MVC特性,你只需添加其他的MVC配置(拦截器,格式化处理器,
视图控制器等)。你可以添加自己的WebMvcConfigurer类型的@Configuration类,
而不需要注解@EnableWebMvc。如果希望使用自定义的RequestMappingHandlerMapping,
RequestMappingHandlerAdapter,或ExceptionHandlerExceptionResolver,你可以声明
一个WebMvcRegistrationsAdapter实例提供这些组件。
如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc
注解。
4. 如何修改SpringBoot的默认配置
4.1 修改SpringBoot的默认配置
模式:
1. SpringBoot在自动配置很多组件时,先看容器有没有用户自己配。(@Bean,@Component)
如果有就用用户配置的,没有就自动配置。
如果有些组件可以有多个,将用户配置的和自己默认的组合起来。
4.2 扩展SpringMVC的自动配置
扩展SpringMVC的自动配置
<mvc:view-controller path="/hello" view-name="success"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean></bean>
</mvc:interceptor>
</mvc:interceptors
1.编写一个配置类(@Configuration),是WebMvcConfigurer类型;不能标注@EnableWebMvc
//使用WebMvcConfigurer来扩展SpringMVC的自动配置
@Configuration
public class MyConfig implements WebMvcConfigurer {
//注意2.0以上不再实现WebMvcConfigurerAdapter
}
2.要什么功能,就重写WebMvcConfigurer中的方法
ctrl+o:打开可以重写的方法列表
3.比如我们要添加一个视图映射
//使用WebMvcConfigurer来扩展SpringMVC的自动配置
@Configuration
public class MyConfig implements WebMvcConfigurer {
//注意2.0以上不再实现WebMvcConfigurerAdapter
//添加一个自定义的视图映射
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//定义规则:哪些请求访问哪些页面。
//如果仅仅只是访问页面,不传数据的话,就可以配置这个,不用在controller在写空方法了
registry.addViewController("/atguigu").setViewName("success");
}
}
扩展SpringMVC自动配置,即保留了所有的自动配置,也能用我们扩展的配置。
4.3 全面接管SpringMVC
SpringBoot对SpringMVC的自动配置不需要了,所有的都是我们自己配置。
我们需要在配置类中添加@EnableWebMvc,所有的SpringMVC场景的自动配置都失效了。
5. 注意 xxxConfigurer
在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置。