其官网:https://www.thymeleaf.org/
看一下官网的解释:
Thymeleaf是⾯向Web和独⽴环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚⾄纯⽂本。
Thymeleaf旨在提供⼀个优雅的、⾼度可维护的创建模板的⽅式。 为了实现这⼀⽬标,Thymeleaf建⽴在⾃然模板的概念上,将其逻辑注⼊到模板⽂件中,不会影响模板设计原型。 这改善了设计的沟通,弥合了设计和开发团队之间的差距。
Thymeleaf从设计之初就遵循Web标准——特别是HTML5标准 ,如果需要,Thymeleaf允许您创建完全符合HTML5验证标准的模板。
看说明,可以得出好像说了什么,又好像什么都没有说。因为我也不知道说什么,不过 SpringBoot推荐的模板引擎就是Thymeleaf。
不过现在不结合SpringBoot使用这个模板。直接同前面所学的servlet进行整合来使用,这样虽然麻烦点,但是至少学习这个模板,不会对其它的基础有要求。
这个可以下载jar包,或者使用maven进行依赖环境配置:
搞这个需要的两个jar 包,既然是javaweb项目,所以必然有servlet这个jar包,还有一个thymeleaf的jar包:
servlet-api-***.jar
thymeleaf*.*.**.RELEASE
其中* 是数字表示的是版本号,所以不再多说什么。
如果使用maven配置:
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleafartifactId>
<version>3.0.12.RELEASEversion>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>4.0.1version>
<scope>providedscope>
dependency>
然后在IDE中创建一个Javaweb项目。
如果不知道如何在IDE中创建web项目:
既然启动Thymeleaf模板,那就是有要解析这个模板的类,看一下官网解释:
除了解释器,还有对 模版引擎的配置,这些就看了,一般会通过配置一个父类的servlet对加载的thymeleaf模板页面进行处理。然后自己的逻辑的servlet继承这个父类即可。
所以创建一个父类的servlet:
package com.xzd.servlet;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
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);
}
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());
}
}
同事还需与在web.xml中配置一些参数来满足:
// ②设置前缀
String viewPrefix = servletContext.getInitParameter("view-prefix");
templateResolver.setPrefix(viewPrefix);
// ③设置后缀
String viewSuffix = servletContext.getInitParameter("view-suffix");
templateResolver.setSuffix(viewSuffix);
具体配置如下:
<context-param>
<param-name>view-prefixparam-name>
<param-value>/param-value>
context-param>
<context-param>
<param-name>view-suffixparam-name>
<param-value>.htmlparam-value>
context-param>
先看一下整体结构
首先创建逻辑servlet类,其基础父类的servlet
//通过注释而配置servlet的 url 这样可以更加直观看web.xml中为thymeleaf做了什么
@WebServlet("/testservelt")
public class testservlet extends ViewBaseServlet{
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession httpSession= req.getSession();
List list=new ArrayList();
list.add("战神");
list.add("艾尔登法环");
list.add("卧龙苍天陨落");
list.add("霍格沃茨:遗产");
httpSession.setAttribute("list",list);
// //此处的视图名称是 index
// //那么thymeleaf会将这个 逻辑视图名称 对应到 物理视图 名称上去
// //逻辑视图名称 : testservlet 为了一致所以 html和servlet名字一样,当然也可以不一样
// //物理视图名称 : view-prefix + 逻辑视图名称 + view-suffix
// //所以真实的视图名称是: /WEB-INF/html/ testservlet .html
super.processTemplate("testservlet",req,resp);
}
}
看一下web.xml中的配置
DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>view-prefixparam-name>
<param-value>/WEB-INF/html/param-value>
context-param>
<context-param>
<param-name>view-suffixparam-name>
<param-value>.htmlparam-value>
context-param>
web-app>
然后写一个页面,不要关心thymeleaf的语法问题,主要是为了演示:
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
<style>
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid black;
}
#gameid {
margin: 12px auto;
collapse: 1px;
}
td {
text-align: center;
width: 160px;
}
style>
head>
<body>
<table id="gameid">
<tr>
<th class="w20">游戏名th>
<th>操作th>
tr>
<tr th:if="${#lists.isEmpty(session.list)}">
<td colspan="4">对不起,库存为空!td>
tr>
<tr th:unless="${#lists.isEmpty(session.list)}" th:each="gamename : ${session.list}">
<td><a th:text="${gamename}" href="#">默认没有如果不是通过服务器启动,就显示这个文本a>td>
<td><a th:text="购买" href="#">默认没有如果不是通过服务器启动,就显示这个文本a>td>
tr>
table>
body>
html>
为了方便,在index.jsp中写一个转发:
Hello World!
<%--转发到自己配置的url上--%>
然后访问:http://localhost:8080/thymeleaf_web/
然后看一下结果:
只要有例子了,后面就直接聊语法了,因为按照上面配置环境肯定没问题。
Thymeleaf 模板引擎支持多种表达式:
th:text 是用来修改标签文本值,比如:
<p th:text="th表达式text的值">P标签体原始值p>
其实例子中也可以看出其在演示时候输出的是th:text的值。不过需要注意其使用不同,显示的值也是不同的。
修改value属性值,比如:
<input type="text" th:value="1111111" value="2222222">
也是如果是服务器启动页面显示是1111111,如果是普通浏览器打开那就是2222222。
意思是解析URL地址,还是演示:
<p th:text="@{/aaa/bbb/ccc}">p>
但是IDE会提示报错,不过不会影响运行结果;
看一下结果就明白了:
会自动在前面添加项目名字,因为我创建的项目名字就是thymeleaf_web。
这个语法的好处是:实际开发过程中,项目在不同环境部署时,Web应用的名字有可能发生变化。所以上下文路径不能写死。而通过@{}动态获取上下文路径后,不会出错误。
对于web项目中的域不了解的话可以看一下,前面的文章:传送阵
直接演示常用的请求域,会话域,以及应用域。
首先咋servelt中创建数据
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("request_data", "request_data");
HttpSession httpsession= req.getSession();
httpsession.setAttribute("session_data","session_data");
ServletContext servletContext=getServletContext();
servletContext.setAttribute("application_data","application");
super.processTemplate("testservlet",req,resp);
}
}
然后再页面如此操作:
<p th:text="${request_data}"> p>
<p th:text="${session.session_data}"> p>
<p th:text="${application.application_data}"> p>
可以看出后台传递的数据,再thymeleaf中呈现文本显示的适合其值格式如下:
th:text="${}"
得到url中的参数,这个还是来一个例子:
http://localhost:8080/thymeleaf_web/?username=张三&favourite=篮球&favourite=rap
然后看例子:
<p th:text="${param.username}"> p>
<p th:text="${param.favourite}"> p>
<p th:text="${param.favourite[0]}"> p>
<p th:text="${param.favourite[1]}"> p>
看结果就明白了。
jsp中有内置对象,对于thymeleaf 也不例外,这个直接列举了。
Thymeleaf 中常用的内置基本对象如下:
来一个例子:
<p th:text="${#request.getContextPath()}">p>
<p th:text="${#request.getAttribute('请求域中数据值')}">p>
除了能使用内置的基本对象外,变量表达式还可以使用一些内置的工具对象。
来一个例子:
<p th:text="${#dates.createNow()}">p>
使用th:fragment来给这个片段命名:
先创建一个test.html
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div th:fragment="fragment_name" id="fragment_id">
<span>抽取的啊公共页面片段span>
div>
body>
html>
具体路径是:
在 Thymeleaf 中,我们可以使用以下 3 个属性,将公共页面片段引入到当前页面中。
使用上 3 个属性引入页面片段,都可以通过以下 2 种方式实现。
通常情况下,~{} 可以省略,其行内写法为 [[~{...}]] 或 [(~{...})],其中 [[~{...}]] 会转义特殊字符,[(~{...})] 则不会转义特殊字符。
现在演示一下:
<p> 这个是调用的页面啊p>
<div th:insert="/utils/test::fragment_name">div>
<div th:insert="/utils/test::#fragment_id">div>
这个需要借助一下serlvet才行,所在servert中配置:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("htmllabel", "测试");
super.processTemplate("testservlet",req,resp);
}
}
然后再html中如此写:
<p>有转义效果:[[${htmllabel}]]p>
<p>无转义效果:[(${htmllabel})]p>
先看结果:
可以看出如果传递的数据带有html标签要求可以在页面。
[[${ 内容 }]]: 显示完整的数据,哪怕是标签也会当作文本显示
[(${ 内容 })] 会让传递数据中的html标签其效果
既然是模板,那肯定也会又逻辑判断以及迭代的语句,所以下面简单的聊一下。
让标记了th:if、th:unless的标签根据条件决定是否显示。
其实这个两个例子前面例子演示了,还是直接黏贴过来:
<tr th:if="${#lists.isEmpty(session.list)}">
<td colspan="4">对不起,库存为空!td>
tr>
<tr th:unless="${#lists.isEmpty(session.list)}" th:each="gamename : ${session.list}">
简单理解可以将th:if和th:unless 理解为 java中的 if ------if not-----
其中的th: if还可以搭配not关键字使用,比如上面th:unless可以如下写:
<tr th:unless="${#lists.isEmpty(session.list)}">tr>
替代为:
<tr th:if="${not #lists.isEmpty(session.list)}">>tr>
有if的必然有这个关键字。
th:switch 与 Java 的 switch case语句类似通常与 th:case 配合使用,根据不同的条件展示不同的内容
还是直接演示:
<div th:switch="${session.game.id}">
<p th:case=" 1">艾尔登法环p>
<p th:case=" 2">战神p>
div>
th:each 遍历,支持 Iterable、Map、数组等。
这个其实在演示的例子中用了:
<tr th:unless="${#lists.isEmpty(session.list)}" th:each="gamename : ${session.list}">
<td><a th:text="${gamename}" href="#">默认没有如果不是通过服务器启动,就显示这个文本a>td>
<td><a th:text="购买" href="#">默认没有如果不是通过服务器启动,就显示这个文本a>td>
当然thymeleaf的语法还有很多,现在不过多阐述了,可以具体使用的时候可以聊,同时还有一点那就是如何整合springmpv,springboot等,这些再用的时候演示如何配置,这里就不再多说了。