thymeleaf
依赖:1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置: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# THYMELEAF (ThymeleafAutoConfiguration)
#开启模板缓存(默认值:true)
spring.thymeleaf.cache=true
#Check that the template exists before rendering it.
spring.thymeleaf.check-template=true
#检查模板位置是否正确(默认值:true)
spring.thymeleaf.check-template-location=true
#Content-Type的值(默认值:text/html)
spring.thymeleaf.content-type=text/html
#开启MVC Thymeleaf视图解析(默认值:true)
spring.thymeleaf.enabled=true
#模板编码
spring.thymeleaf.encoding=UTF-8
#要被排除在解析之外的视图名称列表,用逗号分隔
spring.thymeleaf.excluded-view-names=
#要运用于模板之上的模板模式。另见StandardTemplate-ModeHandlers(默认值:HTML5)
spring.thymeleaf.mode=HTML5
#在构建URL时添加到视图名称前的前缀(默认值:classpath:/templates/)
spring.thymeleaf.prefix=classpath:/templates/
#在构建URL时添加到视图名称后的后缀(默认值:.html)
spring.thymeleaf.suffix=.html
#Thymeleaf模板解析器在解析器链中的顺序。默认情况下,它排第一位。顺序从1开始,只有在定义了额外的TemplateResolver Bean时才需要设置这个属性。
spring.thymeleaf.template-resolver-order=
#可解析的视图名称列表,用逗号分隔
spring.thymeleaf.view-names=
常见使用:
1、在html页面中引入thymeleaf命名空间,即<html xmlns:th=http://www.thymeleaf.org></html>
,此时在html模板文件中动态的属性使用th:命名空间修饰
2、引用静态资源文件,比如CSS和JS文件,语法格式为”@{}”,如@{/js/blog/blog.js}会引入/static目录下的/js/blog/blog.js文件
3、访问spring-mvc中model的属性,语法格式为”${}”,如${user.id}可以获取model里的user对象的id属性
4、循环1
2
3
4
5
6
7
8
9
10<tr th:each="collect,iterStat : ${collects}">
<th scope="row" th:text="${collect.id}">1</th>
<td >
<img th:src="${collect.webLogo}"/>
</td>
<td th:text="${collect.url}">Mark</td>
<td th:text="${collect.title}">Otto</td>
<td th:text="${collect.description}">@mdo</td>
<td th:text="${terStat.index}">index</td>
</tr>
iterStat称作状态变量,属性有:
index:当前迭代对象的index(从0开始计算)
count: 当前迭代对象的index(从1开始计算)
size:被迭代对象的大小
current:当前迭代变量
even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
first:布尔值,当前循环是否是第一个
last:布尔值,当前循环是否是最后一个
5、判断,在html标签中,加入th:if=”表达式”可以根据条件显示html元素1
2
3<span th:if="${not #lists.isEmpty(blog.publishTime)}">
<span id="publishtime" th:text="${#dates.format(blog.publishTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
</span>
以上代码表示若blog.publishTime时间不为空,则显示时间
6、时间的格式化,1
${#dates.format(blog.publishTime,'yyyy-MM-dd HH:mm:ss')}
表示将时间格式化为”yyyy-MM-dd HH:mm:ss”格式化写法与Java格式化Date的写法是一致的。
7、字符串拼接,有两种形式
比如拼接这样一个URL:/blog/delete/{blogId}
第一种:th:href="'/blog/delete/' + ${blog.id }"
第二种:th:href="${'/blog/delete/' + blog.id }"
8、布局
定义代码片段:1
2
3<footer th:fragment="copy">
? 2016
</footer>
在页面任何地方引入:1
2
3
4
5<body>
<div th:include="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:insert="footer :: copy"></div>
</body>
th:include 和 th:replace区别,include只是加载,replace是替换
也可以在引用模版的时候传参:1
<head th:include="layout :: htmlhead" th:with="title='Hello'"></head>
layout 是文件地址,如果有文件夹可以这样写 fileName/layout:htmlhead
htmlhead 是指定义的代码片段 如 th:fragment=”copy”
下面是一个常用的后台页面布局,将整个页面分为头部,尾部、菜单栏、隐藏栏,点击菜单只改变content区域的页面
1
2
3
4
5
6
7
8
9 <body class="layout-fixed">
<div th:fragment="navbar" class="wrapper" role="navigation">
<div th:replace="fragments/header :: header">Header</div>
<div th:replace="fragments/left :: left">left</div>
<div th:replace="fragments/sidebar :: sidebar">sidebar</div>
<div layout:fragment="content" id="content" ></div>
<div th:replace="fragments/footer :: footer">footer</div>
</div>
</body>任何页面想使用这样的布局值只需要替换中见的 content模块即可
1
2
3
4 <html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout">
<body>
<div layout:fragment="content">我是内容</div>
</body>
9、点击事件:th:onclick="'javascript:toxueqiu(\''+${todayBuy.code}+'\')'"
JS中使用1
2
3
4<script th:inline="javascript">
var data = [[${data}]]
//var dd="&&"+"<";
</script>
10、th:style
根据属性值改变背景1
<div class="media-object resource-card-image" th:style="'background:url(' + @{(${collect.webLogo}=='' ? 'img/favicon.png' : ${collect.webLogo})} + ')'" ></div>
11、内嵌变量
为了模板更加易用,Thymeleaf还提供了一系列Utility对象(内置于Context中),可以通过#直接访问:
dates : java.util.Date的功能方法类。
calendars : 类似#dates,面向java.util.Calendar
numbers : 格式化数字的功能方法类
strings : 字符串对象的功能类,contains,startWiths,prepending/appending等等。
objects: 对objects的功能类操作。
bools: 对布尔值求值的功能方法。
arrays:对数组的功能类方法。
lists: 对lists功能类方法
sets
maps
…
举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 ${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')}
${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')}
${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')}
${#dates.createNow()}
${#dates.createToday()}
${#strings.isEmpty(name)}
${#strings.arrayIsEmpty(nameArr)}
${#strings.listIsEmpty(nameList)}
${#strings.setIsEmpty(nameSet)}
${#strings.startsWith(name,'Don')}
${#strings.endsWith(name,endingFragment)}
${#strings.length(str)}
${#strings.equals(str)}
${#strings.equalsIgnoreCase(str)}
${#strings.concat(str)}
${#strings.concatReplaceNulls(str)}
${#strings.randomAlphanumeric(count)}
AOP
添加依赖1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
代码实例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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class HttpAspect {
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
"execution(public * com.gjd.controller.GirlController.*(..))") //该类下所有方法 (
public void log(){
//定义一个全局的切入点 下面 可以直接 log()引用
}
"log()") (
public void doBefore(JoinPoint joinPoint){ //之前执行
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest(); //获取request对象
//url
logger.info("url={}", request.getRequestURL());
//method
logger.info("method={}", request.getMethod());
//ip
logger.info("ip={}", request.getRemoteAddr());
//类方法
logger.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
//通过JoinPoint对象获取类方法的对象
//参数
logger.info("args={}", joinPoint.getArgs());
//通过JoinPoint对象获取传入的对象
}
"log()") (
public void doAfter() { //之后执行
logger.info("222222222222");
}
"object", pointcut = "log()") //获取调用方法返回的信息 (returning =
public void doAfterReturning(Object object) {
logger.info("response={}", object.toString());
}
}
日志
一、设置项目启动的日志等级
1 在运行命令后加入–debug标志,如:$ java -jar springTest.jar –debug
2 在application.properties中配置debug=true,该属性置为true的时候,核心Logger
(包含嵌入式容器、hibernate、spring)会输出更多内容,但是你自己应用的日志并不会输出为DEBUG级别。
二、日志输出路径
默认情况下,Spring Boot将日志输出到控制台,不会写到日志文件。如果要编写除控制台输出之外的日志文件,则需在application.properties中设置logging.file或logging.path属性。
1 logging.file,设置文件,可以是绝对路径,也可以是相对路径。如:logging.file=my.log
2 logging.path,设置目录,会在该目录下创建spring.log文件,并写入日志内容,如:logging.path=/var/log
如果只配置 logging.file,会在项目的当前路径下生成一个 xxx.log 日志文件。
如果只配置 logging.path,在 /var/log文件夹生成一个日志文件为 spring.log
注:二者不能同时使用,如若同时使用,则只有logging.file生效
三、日志级别控制
1 logging.level.com.dudu=DEBUG:com.dudu包下所有class以DEBUG级别输出
2 logging.level.root=WARN:root日志以WARN级别输出
四、自定义日志配置
使用logback,建议使用官方名称logback-spring.xml, logback-spring.groovy, logback.xml, logback.groovy;
spring boot可以为它添加一些spring boot特有的配置项。
如果你即想完全掌控日志配置,但又不想用logback.xml作为Logback配置的名字,可以通过logging.config属性指定自定义的名字:
logging.config=classpath:logging-config.xml
五、logback例子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
28
29
30
31
32
33
34
35
36
37
38
39
40
41<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<property name="log.path" value="E:\\test\\logback.log" />
<!--输出到控制台-->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>-->
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<!--表示只保留最近30天的日志-->
<totalSizeCap>1GB</totalSizeCap>
<!--设置为1GB的话,那么到了这个值,就会删除旧的日志。-->
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="file" />
</root>
<!-- logback为java中的包 -->
<logger name="com.dudu.controller"/>
<!--logback.LogbackDemo:类的全路径 -->
<logger name="com.dudu.controller.LearnController" level="WARN" additivity="false">
<appender-ref ref="console"/>
</logger>
</configuration>
注:
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
2
%d{HH: mm:ss.SSS}——日志输出时间
%thread——输出日志的进程名字,这在Web应用以及异步任务处理中很有用
%-5level——日志级别,并且使用5个字符靠左对齐
%logger{36}——日志输出者的名字
%msg——日志消息
%n——平台的换行符
六、开发,测试环境切换
1 必须在该文件名logback-spring.xml文件写1
2
3
4
5
6
7
8<!-- 测试环境+开发环境. 多个使用逗号隔开. -->
<springProfile name="test,dev">
<logger name="com.dudu.controller" level="info" />
</springProfile>
<!-- 生产环境. -->
<springProfile name="prod">
<logger name="com.dudu.controller" level="ERROR" />
</springProfile>
2 可以启动服务的时候指定 profile (如不指定使用默认),如指定prod 的方式为:java -jar xxx.jar –spring.profiles.active=prod
热部署
pom文件添加1
2
3
4
5<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
加载文件
资源文件1
2
"classpath:test.properties") (
xml文件1
2
3
"classpath:application-bean.xml"}) (locations={
//locations= {"file:d:/test/application-bean1.xml"}
文件上传
跟springMVC类似 配置从xml转向注解1
2
3
4
5
6
7
8
9
10
11
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//// 设置文件大小限制 ,超了,页面会抛出异常信息,这时候就需要进行异常信息的处理了;
factory.setMaxFileSize("128KB"); //KB,MB
/// 设置总上传数据总大小
factory.setMaxRequestSize("256KB");
//Sets the directory location where files will be stored.
//factory.setLocation("路径地址");
returnfactory.createMultipartConfig();
}