Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker,jsp 等传统 Java 模板引擎同,
Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,
此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;
当通过 Web 应用程序(Servlet)访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
直接看例子:
准备工作: DAO
public interface FruitDao {
//获取所有的库存列表信息
List<Fruit> getFruitList();
}
public class FruitDaoImpl extends BaseDao<Fruit> implements FruitDao {
@Override
public List<Fruit> getFruitList() {
return super.executeQuery("select * from t_fruit");
}
}
Thymeleaf - 视图模板技术
1) 添加thymeleaf的jar包
2) 新建一个Servlet类ViewBaseServlet,有两个方法一个初始化一个处理模板,
这个方法可以帮我们完成资源的转发,并且数据的渲染
public class ViewBaseServlet extends HttpServlet {
private TemplateEngine templateEngine;
@Override
public void init() throws ServletException {
// 1.获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 2.创建Thymeleaf解析器对象
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext);
// 3.给解析器对象设置参数
// ①HTML是默认模式,明确设置是为了代码更容易理解
templateResolver.setTemplateMode(TemplateMode.HTML);
// ②设置前缀
String viewPrefix = servletContext.getInitParameter("view-prefix");
templateResolver.setPrefix(viewPrefix);
// ③设置后缀
String viewSuffix = servletContext.getInitParameter("view-suffix");
templateResolver.setSuffix(viewSuffix);
// ④设置缓存过期时间(毫秒)
templateResolver.setCacheTTLMs(60000L);
// ⑤设置是否缓存
templateResolver.setCacheable(true);
// ⑥设置服务器端编码方式
templateResolver.setCharacterEncoding("utf-8");
// 4.创建模板引擎对象
templateEngine = new TemplateEngine();
// 5.给模板引擎对象设置模板解析器
templateEngine.setTemplateResolver(templateResolver);
}
//processTemplate:处理模板,第一个参数:模板(视图)名称,第二个参数:请求 第三个参数:响应
//这个方法可以帮我们完成资源的转发,并且数据的渲染,他可以帮我们完成
protected void processTemplate(String templateName, HttpServletRequest req, HttpServletResponse resp) throws IOException {
// 1.设置响应体内容类型和字符集
resp.setContentType("text/html;charset=UTF-8");
// 2.创建WebContext对象
WebContext webContext = new WebContext(req, resp, getServletContext());
// 3.处理模板数据
templateEngine.process(templateName, webContext, resp.getWriter());
}
}
3) 在web.xml文件中添加配置
- 配置前缀 view-prefix
- 配置后缀 view-suffix
<!-- 在上下文参数中配置视图前缀和视图后缀 -->
<context-param>
<param-name>view-prefix</param-name>
<param-value>/</param-value>
</context-param>
<context-param>
<param-name>view-suffix</param-name>
<param-value>.html</param-value>
</context-param>
4) 创建Servlet类使得我们继承ViewBaseServlet(这个类不需要掌握,后面都被框架封装了)
thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
假设有页面地址:/ index . html 这样的地址可以直接访问到页面本身,我们称之为:物理视图。而将物理视图中前面、后面的固定内容抽取出来,让每次请求指定中间变化部分即可,那么中间变化部分就叫:逻辑视图。
物理视图:将请求转发到一个HTML页面文件时,使用的完整的转发路径就是物 理视图。
逻辑视图:物理视图=视图前缀+逻辑视图+视图后缀
例如:上面的例子:逻辑视图的名称:index
所以拼接后的视图:view-prefix+逻辑视图名称+view-suffix
/ + index + html
@WebServlet("/Index")
public class IndexServlet extends ViewBaseServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取FruitList,所以调用dao的方法,得到list集合
FruitDao fruitDao=new FruitDaoImpl();
List<Fruit> fruitList = fruitDao.getFruitList();
//保存到session作用域
HttpSession session = request.getSession();
session.setAttribute("fruitList",fruitList);
//此处的视图名称是index
//那么thymeleaf会将这个逻辑视图名称对应到物理视图名称上去
//逻辑视图名称:index
//物理视图名称:view-prefix+逻辑视图名称+view-suffix
//所以真实的视图名称是: / + index + .html
//所以跳转的页面就是index.html
//response.sendRedirect("index.html")意思是告诉客户端再次发请求给index.html要把他换成下面的
//index是逻辑视图名称请求到viewBaseServlet方法里面去拼接
super.processTemplate("index",request,response);
}
}
模板+数据
th:th属性赋予每个标签与后台交互的能力,当html文件在本地直接用浏览器打开,浏览器引擎会忽略掉th属性,只是加载静态页面,当把html文件放到服务容器访问,th属性与后台交互,获取数据替换原先的内容,这样前端工程师在编写html页面时,在本地开发,正常实现页面逻辑效果即可,数据先写死,当放到服务容器时数据从后台获取。
th:text作用:
- 不经过服务器解析:直接用浏览器打开HTML文件,看到的是『标签体原始值』
- 经过服务器解析:Thymeleaf引擎根据th:text属性指定的『标签体新值』去替换『标签体原始值』
th:if 一般和unless配合使用
th:unless:否则的意思
each:迭代也就是循环
<html xmlns:th="http://www.thymeleaf.org">
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div id="div_container">
<div id="div_fruit_list">
<p class="center f30">欢迎使用水果库存后台管理系统 </p>
<table id="tbl_fruit">
<tr>
<th class="w20">名称</th>
<th class="w20">单价</th>
<th class="w20">库存</th>
<th>操作</th>
<!-- lists公共内置对象:用来判断集合相关的
is.Empty判断是否为空
unless:否则的意思
each:迭代也就是循环 遍历出来的每一个元素的名字 : ${要遍历的集合}
拿到临时变量;fruit
循环一次就把这里面的一个元素fruitList赋给fruit
text:设置td内部的文本,静态页面会写死了,显示苹果,经过thymeleaf渲染会把${fruit.fname}覆盖到苹果哪里
-->
</tr>
<tr th:if="${#lists.isEmpty(session.fruitList)}">
<td colspan="4">sorry,库存为空!</td>
<tr th:unless="${#lists.isEmpty(session.fruitList)}" th:each="fruit : ${session.fruitList}">
<td th:text="${fruit.fname}">苹果</td>
<td th:text="${fruit.price}">5</td>
<td th:text="${fruit.fcount}">20</td>
<td><img src="imgs/del.jpg" class="delImg"/></td>
</tr>
</table>
</div>
</div>
</body>
</html>
index请求 ---> indexServlet ---> 调用Dao层进行数据查询(数据库操作),和返回数据,把数据保存到session保存作用域中 ---> 在调用viewBaseServlet的方法(进行调用index,进行拼接(拼接到视图前后缀的中间),拼接后 / index . html)也就是thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去 ---> 跳转到index.html页面上 ---> 然后把动态页面整合进来,也就是渲染。