文章目录
Thymeleaf快速入门(Spring版)
1、Thymeleaf概述
- 什么是Thymeleaf?> Thymeleaf是适用于Web和独立环境的现代服务器端>
> Java模板引擎>
> 。> > 官网:Thymeleaf - 什么是Java模板引擎?> 模板引擎不是某一特定领域的技术,它是跨领域跨平台的概念。本文要讲的Java领域的模板引擎,Java模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档(这个特定的文档可以称之为模板,模板中套用不同的数据展示不同的视图,从而实现动态交互),用于网站的模板引擎就会生成一个标准的HTML文档> > 简而言之,Java模板引擎本质就是一个特定的文档,当我们注入不同的数据,该文档会被解析成不同的HTML文档,从而展示不同的网页> > ---> > 较为常见的Java模板引擎有:JSP、Thymeleaf、FreeMaker、Velocity等模板引擎
- Thymeleaf的特点:- 动静结合。Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。- 开箱即用。Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。- 多方言支持。它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。- 与SpringBoot完美整合。SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合
- Thymeleaf的优点:- 动态交互。一个模板注入不同的数据,会展示不同的网页- 动静分离。 Thymeleaf使用HTML通过一些特定标签语法代表其含义,但并未破坏HTML结构,即使无网络、不通过后端渲染也能在浏览器成功打开,大大方便界面的测试和修改(解决了JSP调试困难的弊端)- 降低了项目的复杂性。Thymeleaf将前后端分离开来,让专业的人干专业的事,避免了JSP的前后端混写的缺点,大大提高了开发效率- 易于使用。Thymeleaf模板引擎被主流的Springboot框架集成,Springboot官方做了很多默认配置,开发者只需编写对应html即可,大大减轻了上手难度和配置复杂度
- Thymeleaf的作用:- 渲染页面。让页面能够动态展示数据- 提高用户体验。即使不启动Web应用,也可以直接在浏览器中打开并正确显示模板页面
2、Thymeleaf快速入门
t_book表:
#mermaid-svg-CrolubCLuAxUUvXb {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CrolubCLuAxUUvXb .error-icon{fill:#552222;}#mermaid-svg-CrolubCLuAxUUvXb .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CrolubCLuAxUUvXb .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-CrolubCLuAxUUvXb .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CrolubCLuAxUUvXb .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CrolubCLuAxUUvXb .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CrolubCLuAxUUvXb .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CrolubCLuAxUUvXb .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CrolubCLuAxUUvXb .marker.cross{stroke:#333333;}#mermaid-svg-CrolubCLuAxUUvXb svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CrolubCLuAxUUvXb .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CrolubCLuAxUUvXb .cluster-label text{fill:#333;}#mermaid-svg-CrolubCLuAxUUvXb .cluster-label span{color:#333;}#mermaid-svg-CrolubCLuAxUUvXb .label text,#mermaid-svg-CrolubCLuAxUUvXb span{fill:#333;color:#333;}#mermaid-svg-CrolubCLuAxUUvXb .node rect,#mermaid-svg-CrolubCLuAxUUvXb .node circle,#mermaid-svg-CrolubCLuAxUUvXb .node ellipse,#mermaid-svg-CrolubCLuAxUUvXb .node polygon,#mermaid-svg-CrolubCLuAxUUvXb .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CrolubCLuAxUUvXb .node .label{text-align:center;}#mermaid-svg-CrolubCLuAxUUvXb .node.clickable{cursor:pointer;}#mermaid-svg-CrolubCLuAxUUvXb .arrowheadPath{fill:#333333;}#mermaid-svg-CrolubCLuAxUUvXb .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CrolubCLuAxUUvXb .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CrolubCLuAxUUvXb .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-CrolubCLuAxUUvXb .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-CrolubCLuAxUUvXb .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CrolubCLuAxUUvXb .cluster text{fill:#333;}#mermaid-svg-CrolubCLuAxUUvXb .cluster span{color:#333;}#mermaid-svg-CrolubCLuAxUUvXb div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CrolubCLuAxUUvXb :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
创建Maven项目
导入依赖
编写组件
测试
编写web.xml
编写实体类
编写Thymeleaf
- Step1:创建Maven项目目录结构:
- Step2:导入依赖
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>Thymeleaf</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!--servlet-api--><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!--junit--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version></dependency><!--===========thymeleaf所依赖的jar包===============--><!--attoparser,用于解析thymeleaf--><dependency><groupId>org.attoparser</groupId><artifactId>attoparser</artifactId><version>2.0.5.RELEASE</version></dependency><!--javassist,用来处理Java字节码的类库--><dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.28.0-GA</version></dependency><!--log4j--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!--slf4j--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.30</version></dependency><!--slf4j-log4j12--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.25</version></dependency><!--ngnl,--><dependency><groupId>ognl</groupId><artifactId>ognl</artifactId><version>3.1.26</version></dependency><!--thymeleaf核心依赖--><dependency><groupId>org.thymeleaf</groupId><artifactId>thymeleaf</artifactId><version>3.0.12.RELEASE</version></dependency><!--unbescape,Java的转义库--><dependency><groupId>org.unbescape</groupId><artifactId>unbescape</artifactId><version>1.1.6.RELEASE</version></dependency><!--========================================--></dependencies><build><plugins><!--tomcat7插件--><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</version><configuration><port>8080</port><!-- <path>/index</path>--></configuration></plugin></plugins></build></project>
- Step3:编写web.xml
<?xml version="1.0" encoding="UTF-8"?><web-appxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- 在上下文参数中配置 --><!--配置视图前缀--><context-param><param-name>view-prefix</param-name><param-value>/html/</param-value></context-param><!--配置视图后缀--><context-param><param-name>view-suffix</param-name><param-value>.html</param-value></context-param></web-app>
- Step4:编写实体类略……
- Step5:编写组件1)数据访问层……2)业务逻辑层……3)控制层ViewBaseServlet
packagecom.hhxy.controller;importorg.thymeleaf.TemplateEngine;importorg.thymeleaf.context.WebContext;importorg.thymeleaf.templatemode.TemplateMode;importorg.thymeleaf.templateresolver.ServletContextTemplateResolver;importjavax.servlet.ServletContext;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;/** * @author ghp * @date 2022/9/21 */publicclassViewBaseServletextendsHttpServlet{privateTemplateEngine templateEngine;/** * 初始化方法 */@Overridepublicvoidinit()throwsServletException{// 1、获取ServletContext对象ServletContext servletContext =this.getServletContext();// 2、创建Thymeleaf解析器对象ServletContextTemplateResolver templateResolver =newServletContextTemplateResolver(servletContext);// 3、给解析器对象设置参数// 3.1 HTML是默认模式,明确设置是为了代码更容易理解 templateResolver.setTemplateMode(TemplateMode.HTML);//3.2 设置前缀String viewPrefix = servletContext.getInitParameter("view-prefix"); templateResolver.setPrefix(viewPrefix);//3.3 设置后缀String viewSuffix = servletContext.getInitParameter("view-suffix"); templateResolver.setSuffix(viewSuffix);//3.4 设置缓存过期时间(毫秒) templateResolver.setCacheTTLMs(60000L);//3.5 设置是否缓存 templateResolver.setCacheable(true);//3.6 设置服务器端编码方式 templateResolver.setCharacterEncoding("utf-8");// 4、创建模板引擎对象 templateEngine =newTemplateEngine();// 5、给模板引擎对象设置模板解析器 templateEngine.setTemplateResolver(templateResolver);}/** * 处理模板 * @param templateName 模板的名字 */protectedvoidprocessTemplate(String templateName,HttpServletRequest req,HttpServletResponse resp)throwsIOException{// 1、设置响应体内容类型和字符集 resp.setContentType("text/html;charset=UTF-8");// 2、创建WebContext对象WebContext webContext =newWebContext(req, resp,getServletContext());// 3、处理模板数据 templateEngine.process(templateName, webContext, resp.getWriter());}}
IndexServletpackagecom.hhxy.controller;importcom.hhxy.pojo.Book;importcom.hhxy.service.BookService;importcom.hhxy.service.imp.BookServiceImp;importjavax.servlet.ServletException;importjavax.servlet.annotation.WebServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjavax.servlet.http.HttpSession;importjava.io.IOException;importjava.util.List;/** * @author ghp * @date 2022/9/21 */@WebServlet("/indexServlet")publicclassIndexServletextendsViewBaseServlet{//1、获取BookService对象privateBookService bookService =newBookServiceImp();protectedvoiddoPost(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{this.doGet(request, response);}protectedvoiddoGet(HttpServletRequest request,HttpServletResponse response)throwsServletException,IOException{//2、调用BookService对象的方法,获取数据List<Book> books = bookService.selectAll();//3、将数据保存到Session域对象中HttpSession session = request.getSession(); session.setAttribute("books",books);/* thymeleaf会将 逻辑视图名称 对应到 物理视图名称 逻辑视图名称:index 物理视图名称:view-prefix(前缀) + 逻辑视图名称 + view-suffix(后缀) 真实的视图名称: /html/ index .html (看web.xml中的配置) */super.processTemplate("index",request,response);}}
- Step6:编写Thymeleaf
<!DOCTYPEhtml><!--一定要记得设置thymeleaf的命名空间--><htmlxmlns:th="http://www.thymeleaf.org"><htmllang="en"><head><metacharset="UTF-8"><title>index</title></head><body><tableborder="1px"align="center"><tr><td>书名</td><td>书的单价</td><td>书的库存</td></tr><trth:if="${#lists.isEmpty(session.books)}"><tdcolspan="4">对不起,库存为空!</td></tr><trth:unless="${#lists.isEmpty(session.books)}"th:each="book : ${session.books}"><tdth:text="${book.getName()}"></td><tdth:text="${book.getPrice()}"></td><tdth:text="${book.getStock()}"></td></tr></table></body></html>
- Step7:测试
3、Thymeleaf基础语法
在使用Thymeleaf之前,我们首先要在页面的
html标签
中声明命名空间。
<htmlxmlns:th="http://www.thymeleaf.org">
- 为什么要引入命名空间?引入命名空间的目的是为了避免命名冲突,比如在Thymeleaf中我们是使用
$
符获取域对象中的值的,当我们页面中引入了JQuery后,在JQuery中使用$
是获取结点对象,这就会产生冲突导致页面无法正常展示。当然不声明Thymeleaf命名空间也是能够使用Thymeleaf的。
Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 语法分为以下 2 类:
- th属性
- 标准表达式语法
3.1 th属性
th:eache
:- status中,有count(获取循环的次数,从1开始)、first(判断是否为第一次循环)、index(获取循环的索引号,从0开始)、event(判断count是否为偶数)、last(判断是否是最后一次循环)、odd(判断count是否为奇数)、size(获取集合的长度)<trth:each="employee,status : ${employees}"><tdth:text="${status.count}"></td></tr>
拓展:
th:field
:获取域对象的属性值,后台不能用reques.setAttribute()来传值,可以用model.addAttribute()来传值;而这两种方式th:value都可以接收;在单选框中,当th:field中的属性值与value的值一样,单选框就会被选中
3.2 标准表达式语法
Thymeleaf 模板引擎支持多种表达式:
- 变量表达式:
${...}
- 选择变量表达式:
*{...}
- 链接表达式:
@{...}
- 国际化表达式:
#{...}
- 片段引用表达式:
~{...}
知识拓展:
变量表达式和国际化表达式都属于OGNL(Objects-Graph Navigation Language,对象导航图语言)是应用于Java中的一个开源的表达式语言
3.2.1 变量表达式
变量表达式(Variable Expressions):用于在模板中引用和显示变量的值。例如,
${variable}
表示引用名为
variable
的变量
- 使用
${}
包裹的表达式被称为变量表达式,该表达式具有以下功能:- 获取对象的属性或方法- 获取内置的基本对象并使用- 获取内置的工具对象并使用 ${对象.属性/方法名}
:获取对象的属性或方法//获取对象的方法${book.getName()}
${#内置的基本对象}
:获取内置的基本对象并使用-ctx
:上下文对象-vars
:上下文变量-locale
:上下文的语言环境-request
:HttpServletRequest 对象(仅在 Web 应用中可用)-response
:HttpServletResponse 对象(仅在 Web 应用中可用)-session
:HttpSession 对象(仅在 Web 应用中可用)-servletContext
:ServletContext 对象(仅在 Web 应用中可用)//获取Session域对象中存储的List集合对象//方式一:${#session.getAttribute('books')//方式二:${session.books}
${#内置的工具对象}
:获取内置的工具对象并使用-strings
:字符串工具对象,常用方法有:equals、equalsIgnoreCase、length、trim、toUpperCase、toLowerCase、indexOf、substring、replace、startsWith、endsWith,contains 和 containsIgnoreCase 等-numbers
:数字工具对象,常用的方法有:formatDecimal 等-bools
:布尔工具对象,常用的方法有:isTrue 和 isFalse 等-arrays
:数组工具对象,常用的方法有:toArray、length、isEmpty、contains 和 containsAll 等-lists/sets
:List/Set 集合工具对象,常用的方法有:toList、size、isEmpty、contains、containsAll 和 sort 等-maps
:Map 集合工具对象,常用的方法有:size、isEmpty、containsKey 和 containsValue 等-dates
:日期工具对象,常用的方法有:format、year、month、hour 和 createNow 等//使用内置工具对象 strings 的 equals 方法,来判断字符串与对象的某个属性是否相等${#strings.equals('张三',name)}
3.2.2 选择表达式
选择表达式(Selection Expressions):用于从对象中选择属性或方法。例如,
*{user.name}
表示选择
user
对象的
name
属性。
选择变量也可以称为星号表达式,表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与
th:object
的配合使用。当使用
th:object
存储一个对象后,我们可以在其后代中使用选择变量表达式
*{...}
获取该对象中的属性,其中,
*
即代表该对象
<divth:object="${session.user}"><!--直接获取user对象中的userName属性的值--><pth:text="*{userName}">firstname</p></div>
3.2.3 URL表达式
URL表达式(URL Expressions):用于生成动态URL链接。例如,
@{/path}
会生成相对于当前上下文路径的URL。
- 链接表达式的形式结构如下: - 无参请求:
@{/xxx}
- 有参请求:@{/xxx(k1=v1,k2=v2)}
3.2.3 链接表达式
链接表达式(Link Expressions):类似于URL表达式,用于生成页面内部的锚点链接。例如,
#fragmentId
会生成一个指向具有相应片段标识符的位置的链接。
链接表达式是用于生成页面内部的锚点链接(即片段标识符)。它们使用
#
符号作为前缀,后跟片段标识符。例如,
#fragmentId
会生成一个指向具有相应片段标识符的位置的链接。链接表达式主要用于在同一页面内部进行导航和定位。
<!DOCTYPEhtml><htmlxmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>Link and URL Expression Demo</title></head><body><h1>Link and URL Expression Demo</h1><p>Link Expression:</p><ath:href="#section1">Go to Section 1</a><ath:href="#section2">Go to Section 2</a><p>URL Expression:</p><ath:href="@{/path1}">Link to Path 1</a><ath:href="@{/path2}">Link to Path 2</a><!-- Assume there are corresponding sections and paths in the application --><sectionid="section1"><h2>Section 1</h2><p>This is section 1 content.</p></section><sectionid="section2"><h2>Section 2</h2><p>This is section 2 content.</p></section></body></html>
在上面的示例中,我们使用Thymeleaf的链接表达式和URL表达式创建了一些链接。
链接表达式使用
#
符号,并通过
th:href
属性生成到相应片段标识符的锚点链接。例如,
<a th:href="#section1">Go to Section 1</a>
会生成一个链接,点击后将滚动至具有
section1
片段标识符的位置。
URL表达式使用
@
符号,并通过
th:href
属性生成动态的URL链接。例如,
<a th:href="@{/path1}">Link to Path 1</a>
会生成相对于当前上下文路径的URL,点击后将导航到
/path1
。
3.2.4 国际化表达式
国际表达式使用的基本步骤:
- 配置国际化资源文件:首先,在项目中配置对应的国际化资源文件,按照不同语言创建不同的属性文件,如
messages_en.properties
(英语)、messages_zh_CN.properties
(中文)等。每个属性文件中包含了对应语言的键值对,用于表示不同语言下的文本信息。 - 设置
Locale
解析器:在 Spring MVC 中,需要配置LocaleResolver
来解析用户的语言偏好,并将其应用到 Thymeleaf 视图中。常见的 LocaleResolver 有CookieLocaleResolver
、SessionLocaleResolver
等,你可以根据需求选择合适的LocaleResolver。 - 在 Thymeleaf 模板中使用国际化表达式:在 Thymeleaf 模板中,可以使用国际化表达式来获取对应语言的文本信息。通过
#{}
来包裹键名,Thymeleaf 会根据当前 Locale 自动寻找对应的属性值。例如,<span th:text="#{welcome.message}"></span>
表示从国际化资源文件中获取键为 “welcome.message” 的文本信息并显示在HTML中。
3.2.5 片段引用表达式
Thymeleaf的片段引用表达式(Fragment Expression)是一种在模板中引用和渲染片段的方式。它允许将一个或多个片段从其他模板中提取出来并在当前模板中进行引用和渲染。
Thymeleaf的片段引用表达式使用
~{}
包裹片段名称,并可以传递参数。以下是使用片段引用表达式的基本语法:
复制代码<div th:insert="~{templateName :: fragmentName(parameter1='value1', parameter2='value2')}"></div>
其中,
templateName
表示模板文件名,
fragmentName
表示片段名称。通过
::
符号来连接模板文件名和片段名称。在片段引用表达式中,还可以传递参数给被引用的片段。参数以键值对的形式传递,使用逗号分隔。
示例中的
parameter1
和
parameter2
是片段中定义的参数名称,
value1
和
value2
是要传递的实际值。
使用片段引用表达式可以将片段从其他模板中提取出来并插入到当前模板的指定位置。这有助于模块化开发和代码复用,可以将通用的部分抽离出来,减少重复代码的编写。
需要注意的是,被引用的片段必须在对应的模板文件中存在,并且在片段定义处使用
th:fragment
属性进行标记。例如,在
templateName.html
模板文件中定义一个片段:
html复制代码<div th:fragment="fragmentName">
<!-- 片段内容 -->
</div>
然后在另一个模板中使用片段引用表达式来引用和渲染该片段:
html复制代码<div th:insert="~{templateName :: fragmentName}"></div>
通过使用Thymeleaf的片段引用表达式,我们可以方便地将模板中的特定部分提取出来并在其他模板中重复使用,提高了代码的可维护性和重用性。
参考文章:
- Thymeleaf教程(10分钟入门)
- 代码重工
- OGNL 表达式_MyBatis 入门教程
- ognl概念和原理详解
- cloudfavorites/favorites-web: 云收藏 Spring Boot 2.X 开源项目 (github.com):
版权归原作者 知识汲取者 所有, 如有侵权,请联系我们删除。