第三章(续)Thymeleaf语法(一)

本文详细介绍了Thymeleaf的标准方言,包括变量表达式 `${...}`、选择变量表达式 `*{...}`、消息表达式 `#{...}`、URL链接表达式 `@{...}` 和片段表达式 `~{...}`。通过这些表达式,Thymeleaf可以与Spring框架集成,实现动态内容渲染、国际化、资源链接和模板复用等功能。文中通过示例代码展示了如何在Thymeleaf模板中使用这些表达式,并解释了它们的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Thymeleaf中提供了一套标准方言,这种方言提供了各种处理器,这些处理器可以应用特定的逻辑到某个组件(标签、文本、注释等)对象。并且,对于大多数用户来说,这套标准方言足以满足各种逻辑表达的需求。

官方提供的Thymeleaf-spring方言,可以刚好地利用spring framework中的一些特性。例如,使用Spring Expression Language 或者Spring EL 代替OGNL。

这些标准方言里的处理器,都属于属性处理器,这使得浏览器在处理之前也能正确显示HTML模板文件内容,因为对于未定义的额外属性,会被直接忽略。这样可以帮助设计人员和开发人员使用完全相同的模板文件,减少将静态原型转换为工作模板文件所需的各项工作。我们称此为:自然模板。

这里将从一下几个方面介绍Thymeleaf的基本语法:

  • Thymeleaf 表达式
  • Thymeleaf支持的字面值
  • Thymeleaf支持的运算
  • Thymeleaf常用的th:*属性
  • Thymeleaf表达式基本对象
  • Thymeleaf表达式工具对象

Thymeleaf 表达式

作为Thymeleaf标准方言最重要的组成部分,Thymeleaf提供了各种表达式,用于定制和现实不同类型的内容。

  1. 变量表达式 ${...}
  2. 选择变量表达式(星号表达式)*{...}
  3. 消息表达式 #{...}
  4. URL链接表达式  @{...}
  5. 片段表达式 ~{...}

变量表达式 ${...}

变量表达式用于显示某个变量的值,可以是普通表达式的计算结果,或者是服务器端返回的某个属性的值。

例如:

在ThymeleafController.java中添加以下代码,用于返回数据到视图

/**
 * 这里我们需要使用@Controller注解:因为这个类返回的是视图(View)而不是数据(Data)
 */
@Controller
public class ThymeleafController {

    @GetMapping("/index")
    public String index(Model model, HttpSession session){
        //在model中来存放要返回给客户端的数据key:value,在客户端中通过key获取对应的value
        model.addAttribute("message","Hello World!!!");
        model.addAttribute("result",100+200);
        model.addAttribute("user",new User("alice",123456L,"email","M"));
        session.setAttribute("user2",new User("admin",987654L,"admin@niit.com.cn","L"));
        return "index";//逻辑视图名
    }
}

在index.html模板中添加变量表达式显示各种数据

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1 th:text="${message}">Hi</h1>
    <h1 th:text="${result}">计算结果</h1>
    <h1 th:text="${1>2}">计算结果</h1>
    <h1 th:text="${10*20}">计算结果</h1>
    <div>
         <h1 th:text="${user}">user对象</h1>
         <h1 th:text="${user.username}">显示用户名</h1>
         <h1 th:text="${user.pwd}">显示用户密码</h1>
    </div>
    <div>
        <h1 th:text="${session.user2}">显示session作用域中的user2对象</h1>
        <h1 th:text="${session.user2.username}">显示session作用域中的user2对象的用户名</h1>
    </div>
    <h1 th:text="${'id:'+user.username+',pwd:'+user.pwd}">user information</h1>
</body>
</html>

        测试后发现${}的内容会作为表达式处理,${message}显示服务器返回的 message 属性的值, ${10*20}和${1>2}作为常规表达式被计算后显示计算结果在页面上,${result}显示 result 属性 的值,${user.username}和${user.pwd}分别显示 user 属性(一个 User 对象)中 username和 pwd属性的值,${session.user2}和${session.user2.username}分别显示session范围属性 user2 ( 一 个 User 对 象 ) 的 username 属 性 的 值 , session 为 内 置 对 象 , 最 后 的 ${'id:'+user.username+',pwd:'+user.pwd}表达式中,单引号内容为要连接的字符串, 字符串连接使用+运算符实现。

选择变量表达式(星号表达式)*{...}

        该表达式用于内层引用外层对象,从而简化表达式的书写,列入对于变量表达式中我么书写用户对象的方式${user.useranme}${user.pwd}可以用以下代码实现。

    <div th:object="${user}">
        <h1 th:text="*{username}">显示用户名</h1>
        <h1 th:text="*{pwd}">显示用户密码</h1>
    </div>

        在上述代码中,可以在要使用选择表达式的内容外部嵌套一个 div 或其他标记,并使用 th:object 属性 和变量表达式指定引用的对象,也就是和一个对象进行绑定,这样在内容部分直接使用*{}表达式根 据属性名获取对应的属性值即可,无需再写属性的完整表达式。

消息表达式 #{...}

        消息表达式可用于读取和显示文本文件中的内容,如属性文件,主要用于显示读取的文本消息或实 现国际化。

        例如:在 src/main/resources 目录下新建一个目录,用于存放一些属性文件,假设目录名叫做 props, 在目录下新建一个属性文件,假设名为 tips.properties,用于存储一些提示信息,添加如下代码:

msg.welcome=Hi,欢迎来学习Thymeleaf
msg.error=Sorry,网站出现了一些异常,请等待工程师维护...

        其中 msg.welcome 和 msg.error 为键的名称,也就是属性名称,等号后面的内容分别是两个属性的 值,后续可以根据键的名称获取值。

然后,在 application.yml中添加如下代码:

spring:
  messages:
    basename: props/tips

        其中,spring .messages.basename 属性用于指定属性文件的位置,书写方式为文件路径方式 (props/tips),而不是包名方式(props.tips),props 为属性文件所在的目录,tips 为属性文件的名称,如 果有多个属性文件,可以用逗号隔开,分别给出每个属性文件的位置,如 props/tips, props/index, i18n/index/index

        最后,在模板页面上使用消息表达式读取和显示属性文件中的信息:

<p th:text="#{msg.welcome}"></p>
<p th:text="#{msg.error}"></p>

        运行效果

         对于实现国际化,则需要根据用户选择的显示语言,发送请求参数,配置 LocaleResolver,应用请求 参数的值,进而读取对应的属性文件的内容,显示在页面上。

URL 链接表达式: @{...}

        在 web 开发中,页面中不可避免的要使用资源链接,不管引入 css、js、图片等,还是设置超链接的 href 属性或图片的 src 属性。为了区分请求的 url,很多时候我们会给请求添加一定的前缀,如学生请 求添加/studens 作为前缀,管理员可以添加/master 作为前缀,诸如此类。添加前缀导致的一个问题是 随着请求 url 的不断变化,访问使用了相对路径的资源可能会遇到 404 错误,这样开发人员就需要考 虑在页面中使用上下文路径来设置资源链接。Thymeleaf 提供链接表达式来实现资源的引用,这样不 论请求的 url 如何变化,链接的资源的路径总会是正确的。

        下面的例子列举了使用链接表达式的链接:

<head>
    <link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
    <link rel="stylesheet" th:href="@{/css/login.css}">
    <script th:src="@{/js/jquery-3.4.1.min.js}"></script>
    <script th:src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div class="container">
        <img th:src="@{/images/1.jpg}" width="200" height="150"> <br><br>
        <a th:href="@{https://www.baidu.com}">Baidu</a><br>
        <a th:href="@{/toIndex}">Home</a><br>
        <a th:href="@{/product(pid=P001)}">View details</a><br>
        <a th:href="@{/product(pid=${proId})}">View details</a><br>
        <a th:href="@{/search1(keyword=Sam,type=1)}">search1</a><br>
        <a th:href="@{/search2/{pid}(pid=P001)}">search2</a><br>
        <a th:href="@{/search3/{pid}/{type}(pid=${proId},type=1)}">
            search3
        </a><br>
        <form th:action="@{/login}">
            Username: <input type="text" name="uname"><br><br>
            Password: <input type="text" name="pwd"><br><br>
            <button>Login</button>
        </form>
    </div>
</body>

对于不同类型的url的表示,见下表(假设端口号为8088,上下文路径为"/")

url表示类型
路径 表达式写法处理结果访问路径
绝对路径@{http://www.baidu.com}http://www.baidu.comhttp://www.baidu.com
页面相对路径@{login}loginhttp://localhost:8088/login
上下文相对路径(/开头)@{/login}/loginhttp://localhost:8088/login
服务器相对路径(~开头)@{~/login}/login(如果自定义了上下文路径,将不显示上下文路径)http://localhost:8088/login
协议相对路径(//开头)@{//login}//loginhttp://login

 片段表达式:~{...}

        片段(Fragment)表达式用于定义模板内容,并在模板页面中引用模板页或模板片段,相当于定义模板 内容,然后可以将该片段在任何模板页面的任何地方使用。例如:我们需要在内容页引入头部和底部页面。

        使用片段表达式有以下几个步骤:

  1. 使用th:fragment标记被引用的部分
  2. 使用th:insert 或者th:replace在主页面引用被fragment标记的部分。
    1. th:insert:  插入要引入的代码,作为当前标签的子标签
    2. th:replace  使用引入的代码替换当前的标签。

        在 src/main/resources/templates 目录下新建一个模板页面 header.html和footer.html,页面中使用以下代码定义 了一个模板片段:

<!--src/main/resources/templates/header.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面头部</title>
</head>
<body>
    <h3 th:fragment="headpage">欢迎来到Thymeleaf的课堂</h3>
</body>
</html>
<!--src/main/resources/templates/footer.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>页面底部</title>
</head>
<body>
  <div th:fragment="footpage">
    Alice All Right Reserved <br/>
    &copy; China ICP No5532-0968
  </div>
</body>
</html>

在上面的页面中 th:fragment定义了一个可用作模板内容的片段,名为 headpage(footpage)。如 果想在其他页面使用该模板片段,直接使用 th:insert 或 th:replace 属性联合片段表达式~{}引用模板片段 即可,代码如下:

在同目录下创建main.html.引入页面头部和底部的代码。这里分别使用th:insert和th:replace

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
  <!--引入页头-->、
  <header th:insert="~{header::headpage}"></header>
  <!--页面内容部分-->
  <section>
    <div>
      这里显示页面的主要内容
    </div>
  </section>
  <!--引入页脚-->
  <footer th:replace="~{footer::footpage}"></footer>
</body>
</html>

        其中 th:insert 属性用于插入一个模板片段的内容,书写使用~{}表达式,表达式中 header(footer) 表示模板片 段所在的页面,headpage(footpage)为模板片段的名称,中间使用::连接。

        运行 main.html 页面,可看到页面插入了模板片段的内容。

th:insert与th:replace的区别:

        th:insert 属性是插入内 容,th:replace 属性是替换内容,也就是说 th:insert 属性是在 <header></header> 标签中插入模板片段, 而 th:replace 属性是直接用模板片段替换<footer></footer>标签,footer元素将不复存在。

        另一种用法是不使用th:fragment片段,直接给片段内容定义一个id,如<div th:fragment="footpage">替换为<div id="foodid">,在使用模板时,则使用<footer th:replace="~{footer::#footid}">来引入模板片段。

关于片段表达式的更多书写格式,可参考下表:

表达式书写说明示例
~{templatename::selector}引用名为 templatename 的模板 页面中名为 selector 的片段~{footer::footpage}
~{templatename::#selector}引用名为 templatename 的模板 页面中 id 为 selector 的片段~{footer::#footpage}
~{templatename}引用名为 templatename 的模 板页面的完整内容~{footer}
~{::selector}或 ~{this::selector}引用当前模板页面中名为 selector 的片段~{::contentDiv} ~{this::contentDiv}
~{::#selector}或 ~{this::#selector}引用当前模板页面中 id 为 selector 的片段引用当前模板页面中 id 为 selector 的片段

 下一篇,介绍Thymeleaf语法(二)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值