
自动配置原理:全局配置文件如何生效
@Conditional派生注解
当@Conditional指定的条件达成时,被@Conditional注解的类才能生效。
注解在类上,在注解的参数中可以指定一些条件,当条件达成时,被注解的类的内容才能生效,否则不生效。
@Conditional扩展注解 | 作用 |
---|---|
@ConditionalOnJava | 系统Java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定Bean |
@ConditionalOnMissingBean | 容器中不存在指定Bean |
@ConditionalOnExpression | 满足SpEL表达式指定 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMissingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的Bean,或者这个Bean是首选Bean |
@ConditionalOnProperty | 系统中有指定的属性是否有指定的值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前是web环境 |
@ConditionalOnNotWebApplication | 当前不是Web环境 |
@ConditionalOnJndi | JNDI存在指定项 |
自动装配
以WebMvc为例
当SpringBoot启动时,会扫描需要自动配置的类,然后加载其配置类,使用全局配置文件覆盖需要替换的配置。
- 自动配置类:xxxAutoConfiguration
- 对应的配置类:xxxProperties
SpringBoot为多个类提供了自动配置类,名为xxxAutoConfiguration,比如:WebMvcAutoConfiguration;
自动配置类中的注解。
1
2
3
4
5
6
7
//@AutoConfiguration表示这是一个自动配置类,这个注解的下面还有@Configuration注解表示这是一个Spring配置类。
//Conditional注解用于表示注解是否需要加载,这里表示如果项目为WebApplication。
//若存在以上几个类
//容器中不存在指定Bean
public class WebMvcAutoConfiguration {...}自动配置类中Conditional注解判断自动配置类是否需要加载。
1
其中@EnableConfigurationProperties注解指向需要使用的配置类。这里是:WebMVCProperties和WebProperties。
xxxProperties类中配置了自动配置类的默认值,并调用@ConfigurationProperties允许在全局配置文件中修改默认值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27//WebMvcProperties类
//可以在配置文件中使用spring.mvc前缀修改其中的值
public class WebMvcProperties {
/**
* Formatting strategy for message codes. For instance, 'PREFIX_ERROR_CODE'.
*/
private DefaultMessageCodesResolver.Format messageCodesResolverFormat;
private final Format format = new Format();//下面测试这个对象的值
...
}
//Format类
public static class Format {
/**
* Date format to use, for example 'dd/MM/yyyy'.
*/
private String date;
/**
* Time format to use, for example 'HH:mm:ss'.
*/
private String time;
...
}比如像这样:
1
2
3
4
5spring:
mvc:
format:
date:
time:
SpringBoot的调试
在配置文件中添加debug=true打开调试模式。
1 | # 可以通过debug查看哪些自动配置类生效,哪些没有生效 |
调试输出内容示例
1 |
|
SpringBoot Web开发 资源路径
静态资源
静态资源放在哪里
静态资源可以放在以下几个目录:
- 自定义的优先级最高
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/ (默认)
- classpath:/public/
在templates下的页面只能通过controller来跳转。
这几个目录会直接引用到页面的根目录。优先级依据上面的顺序执行。
(很少使用webjars)/webjars/**指向由webjars依赖引入的静态文件,如:http://127.0.0.1:8080/webjars/jquery/3.4.1/jquery.js
自定义静态资源位置
1 | spring: |
静态资源访问url:使用spring.mvc.static-path-pattern来配置,如:/res/**,访问时使用http://127.0.0.1:8080/res/1.js
静态资源放在哪里:使用spring.web.resources.static-locations来配置,这里要写数组。如:[ classpath:/yn/],资源要放在以下位置。
源码解释
1 | public void addResourceHandlers(ResourceHandlerRegistry registry) { |
webjars
很少使用webjars
使用依赖可以加入一些js文件。
1 | addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/"); |
代码里指向的就是webjars依赖的位置。这里添加的是jquery.js。
首页配置
默认位于资源目录下的index.html。
可以使用controller自定义。
源码解释
1 | private Resource getIndexHtml(Resource location) { |
通过这个方法得知,项目的首页默认指向为static下的index.html。
图标配置
放在静态资源目录下就可。默认:/favicon.ico
thymeleaf模板引擎
thymeleaf是Java模板引擎之一。
依赖
SpringBoot里使用依赖spring-boot-starter-thymeleaf。
1 | <dependency> |
thymeleaf官方的依赖使用
Module | Group ID | Artifact ID |
---|---|---|
Core library | org.thymeleaf |
thymeleaf |
Spring 3 integration | org.thymeleaf |
thymeleaf-spring3 |
Spring 4 integration | org.thymeleaf |
thymeleaf-spring4 |
Spring 5 integration | org.thymeleaf |
thymeleaf-spring5 |
Testing library | org.thymeleaf |
thymeleaf-testing |
Spring Security 3 integration | org.thymeleaf.extras |
thymeleaf-extras-springsecurity3 |
Spring Security 4 integration | org.thymeleaf.extras |
thymeleaf-extras-springsecurity4 |
Java 8 Time API compatibility | org.thymeleaf.extras |
thymeleaf-extras-java8time |
Tiles 2 integration | org.thymeleaf.extras |
thymeleaf-extras-tiles2 |
IE Conditional Comments support | org.thymeleaf.extras |
thymeleaf-extras-conditionalcomments |
使用
第一个程序
在templates创建html文件;
在controller中返回字符串为html文件的文件名,不包含后缀。
1 |
|
- 测试运行
html中使用
需要头
<html xmlns:th="http://www.thymeleaf.org">
在页面中使用表达式。表达式格式为
th:abc="xxx"
,abc表示内容类型,xxx表示内容。1
2
3
4
5
6
7
8
9
10
11
12
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>一个Templates页面</title>
</head>
<body>
一个Templates页面
<!--所有的html元素可以被thymeleaf替换接管: th:元素名-->
<div th:text="${msg}"></div>
</body>
</html>text为内容,${msg}为引入的值。
在Controller中设置msg的值。
1 |
|
测试运行
作用
可以使用表达式在页面中显示内容。
源码
1 |
|
得知:
- 在配置中使用spring.thymeleaf前缀;
- 默认模板前缀:classpath:/templates/
- 默认模板后缀:.html
thymeleaf模板引擎语法
官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/
Springboot中的一些配置
1 | # 关闭模板引擎的缓存 |
一些表达式
- Simple expressions:
- Variable Expressions:
${...}
//普通变量 - Selection Variable Expressions:
*{...}
- Message Expressions:
#{...}
//国际化消息表达式 - Link URL Expressions:
@{...}
//表示URL - Fragment Expressions:
~{...}
//片段表达式,可以提取网页片段作为一个模块,然后在另一个网页插入。
- Variable Expressions:
- Literals
- Text literals:
'one text'
,'Another one!'
,… //文本使用单引号,不能使用双引导 - Number literals:
0
,34
,3.0
,12.3
,… //数字直接写 - Boolean literals:
true
,false
//布尔值直接写 - Null literal:
null
//null直接写 - Literal tokens:
one
,sometext
,main
,… //字符串文本,如果内容没有一些影响语法的符号(空格,符号),就可以直接写。- 比如
<div th:class="'content'">...</div>
可以用<div th:class="content">...</div>
表达。
- 比如
- Text literals:
- Text operations:
- String concatenation:
+
//文本操作 - Literal substitutions:
|The name is ${name}|
- String concatenation:
- Arithmetic operations:
- Binary operators:
+
,-
,*
,/
,%
- Minus sign (unary operator):
-
- Binary operators:
- Boolean operations:
- Binary operators:
and
,or
//与 或 - Boolean negation (unary operator):
!
,not
//非
- Binary operators:
- Comparisons and equality:
- Comparators:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - Equality operators:
==
,!=
(eq
,ne
)
- Comparators:
- Conditional operators: //条件运算符
- If-then:
(if) ? (then)
- If-then-else:
(if) ? (then) : (else)
//用这个代替前端的if-else - Default:
(value) ?: (defaultvalue)
- If-then:
- Special tokens:
- No-Operation:
_
- No-Operation:
一些属性
这是一些thymeleaf的属性,优先级从上到下依次降低。
Order | Feature | Attributes | 功能 |
---|---|---|---|
1 | Fragment inclusion | th:insert th:replace |
包含,类似include |
2 | Fragment iteration | th:each |
循环 |
3 | Conditional evaluation | th:if th:unless th:switch th:case |
判断 |
4 | Local variable definition | th:object th:with |
|
5 | General attribute modification | th:attr th:attrprepend th:attrappend |
|
6 | Specific attribute modification | th:value th:href th:src ... |
属性 |
7 | Text (tag body modification) | th:text th:utext |
th:text 不转义字符th:utext 转义字符 |
8 | Fragment specification | th:fragment |
提取公共页面 |
9 | Fragment removal | th:remove |
运算符的使用
1 | <button th:href="@{/emp/delete/}+${emp.getId()}">删除</button> |
一些方法的使用
dates.format
可以格式化Date对象的格式。
使用
1 | <td th:text="${#dates.format(emp.getBirth(),'yyyy-MM-dd HH:mm:ss')}">1,001</td> |
用”#”修饰,然后参数输入Date对象和格式’yyyy-MM-dd HH:mm:ss’。
一些属性的使用
th:text,th:utext
th:text下的字符不会进行html转义,th:utext下的字符会进行html转义。
th:text有另一种写法(这个写法一般不用):
1 | <div>[[ ${msg} ]]</div><!-- 这个写法一般不用 --> |
代码
1 | <div th:text="${msg}"></div> |
1 |
|
运行
th:each
可以用来遍历一个数组,使用方法:
在属性中添加
th:each="user:{$users}"
;1
<h3 th:each="user:${users}"></h3>
遍历users,类似for(User user : users){}
通过另一个属性值使用这个值
th:text="${user}"
。1
<h3 th:each="user:${users}" th:text="${user}"></h3>
会出现多个元素,分别对应遍历的一个效果,表现如下:
1
2
3<h3>张三</h3>
<h3>李四</h3>
<h3>王五</h3>
代码
Controller中
1 |
|
html中
1 | <h3 th:each="user:${users}" th:text="${user}"></h3> |
运行结果
th:href 和 @{/js/jquery.js}
th:href修改html元素中的href属性值
可以根据server.servlet.context-path的配置自动在链接前添加内容。
@{/js/jquery.js}一般用在表示链接
如果链接是根目录(/qwe.js)
1 | <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet"> |
在springBoot配置中添加servlet目录
1 | server.servlet.context-path=/yn |
在HTML中的表现
1 | <link href="/yn/css/bootstrap.min.css" rel="stylesheet"> |
如果链接是相对目录(qwe.js)
1 | <link th:href="@{css/bootstrap.min.css}" rel="stylesheet"> |
表现效果:
1 | <link href="css/bootstrap.min.css" rel="stylesheet"> |
若设置server.servlet.context-path后,这个表现效果不会改变。
th:fragment,th:insert,th:replace
分别代表:声明当前区域 插入 替换
th:fragment
th:fragment放在html元素属性中,用于为当前元素声明一个名字。
1 | <!-- common.html --> |
声明时不需要~{…}表达式括住。
th:insert
th:insert也放在元素属性中,会将指定的fragment插入到元素中。
1 | <!-- qwe.html --> |
引用时需要使用~{…}表达式括住。内容为“模板名::元素声明的名字”
表现效果
1 | <div> |
th:replace
th:replace将使用指定的fragment替代原来的元素。
1 | <!-- asd.html --> |
表现效果
1 | <nav>asd</nav><!-- 原本的div被替代了 --> |
传递参数
在insert和replace后面,可以直接加括号传参。
格式:(参数名=’值’)
使用:
对于th:fragment
1 | <!-- commons.html 公共页面 --> |
对于th:replace
1 | <!-- list.html 假定:员工管理页面 --> |
1 | <!-- list.html 假定:主页 --> |
使用场景
这个一般用于多个页面有公共部分时,可以将公共部分放在同一个页面中,然后在别的页面只需要引用就可以了。