Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎,类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎
文档
头部提示
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
数据作用域
import org.springframework.ui.Model;
// 主要是 Model
@GetMapping("/manage")
public String category(HttpServletRequest request, Model model) {
model.addAttribute("config", CommonCache.config);
model.addAttribute("loginFlag", Objects.equals(request.getSession().getAttribute("loginFlag"), true));
model.addAttribute("categoryList", categoryService.listCategory());
return "manageCategory";
}
JSON的解析
<div th:text="${article['content']}"></div>
style
<div th:style="${newCate} eq ${item['cateName']} ? 'display:block' : ''"></div>
或者可读性更强的字面量替换
<tr th:each="item,itemStat:${list}" class="animated fadeInDown" th:style="|animation-delay: ${itemStat.count * 200 + 200}ms|">
<td th:text="${item.id}"></td>
<td th:text="${item.name}"></td>
<td th:text="${item.sort}"></td>
<td th:text="${item.type}"></td>
<td>
<button>编辑</button>
</td>
</tr>
class
th:classappend="${page == pageNnm} ? 'active' : ''"
遍历
<tr th:each="cate:${cateList}">
<td th:text="${cate.sort}"></td>
<td th:text="${cate.name}"></td>
<td>0</td>
<td th:text="${cate.createDate}"></td>
<td th:text="${cate.updateDate}"></td>
</tr>
遍历中的index
<div th:each="item,itemStat : ${hot}">
<span th:text="${itemStat.count}">1</span>
<a th:href="'/article/'+${item.id}" th:text="${item.title}"></a>
</div>
- index:当前迭代对象的index(从0开始计算)
- count: 当前迭代对象的index(从1开始计算)
- size:被迭代对象的大小
- current:当前迭代变量
- even/odd:布尔值,当前循环是否是偶数/奇数(从0开始计算)
- first:布尔值,当前循环是否是第一个
- last:布尔值,当前循环是否是最后一个
图像
<img th:src="@{${session.config.avatar}}">
时间
<div th:text="${#dates.format(article.createDate, 'yyyy-MM-dd')}"></div>
onclick
<span class="option" th:onclick="edit([[${category.cateId}]])">重命名</span>
注意:IDEA会飘红,不影响程序运行,优化可使用HTML5的data-*属性
<!-- 使用 data-id 和 data-name 存储数据,清晰明了 -->
<button class="btn-rename"
th:data-id="${item.id}"
th:data-name="${item.name}"
onclick="renameFun(this)">
重命名
</button>
function renameFun(button) {
// 直接从按钮元素上获取绑定的数据
const id = button.getAttribute('data-id');
const name = button.getAttribute('data-name');
console.log("ID:", id, "名称:", name);
// 你的业务逻辑...
}
下拉选中
<select name="recommend" id="recommend">
<option value="0" th:selected="${article.recommend == 0}">不推荐</option>
<option value="1" th:selected="${article.recommend == 1}">推荐</option>
</select>
解析HTML
<span th:utext="${item.intro}"></span>
模板
创建个html文件,如common.html
<!--底部-->
<div th:fragment="footer">
<span>© 2020</span>
</div>
使用
<!--底部-->
<div th:replace="~{common::footer}"></div>
注意:模板需要放在templates目录下,不然无法找到
重定向和转发
redirect: 重定向,没有数据
forward: 请求转发,带数据,默认
如:return "redirect:/";
自定义错误页面
在templates下创建error文件夹,放入错误页的html
4xx代表4开头的错误,也可以创建具体的每个状态页面,比如404、400,也可以定义带信息
import com.fan.cache.CommonCache;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 错误页面
*/
@Controller
public class ErrorCustomController implements ErrorController {
@RequestMapping("/error")
public String error(Model model) {
model.addAttribute("config", CommonCache.config);
return "500";
}
}
script绑定数据
<script th:inline="javascript">
// 语法 [[${article.content}]]
$('#content').html(marked([[${article.content}]]))
// 同样可以使用判断
$('#content').html(marked([[${article != null ? article.content : ''}]]))
</script>
input数据绑定
<input id="title" type="text" placeholder="标题" th:value="${document.name}">
textarea数据绑定
<textarea id="content" placeholder="内容" th:text="${document.content}"></textarea>
if条件
<ul>
<li>首页</li>
<!-- 只有管理员登录时,才显示后面这两个 li,且不会多出多余的 div 标签 -->
<th:block th:if="${user.isAdmin}">
<li>用户管理</li>
<li>系统设置</li>
</th:block>
<li>退出登录</li>
</ul>
拦截器未登录重定向到404
可以配合自定义错误页面使用
/**
* 请求拦截,权限控制
*/
@NonNullApi
@Slf4j
public class ReqInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
Object loginFlag = request.getSession().getAttribute("loginFlag");
if (Objects.nonNull(loginFlag)) {
return true;
}
// 重定向到404页面
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return false;
}
}