Thymeleaf

问题

前后端如何进行分工?

jsp已经没落了,基本不再建议使用,而且在SpringBoot中已经不再建议使用jsp编写页面。SpringBoot针对同步应用开发建议使用Thymeleaf模板引擎

Thymeleaf的基本思路:

  • 前后端使用同一个html页面,只是前端使用浏览器直接打开,后端是通过特定的解析器打开

    <h1 bbb="ccc">  由于html的h1标签上并没有bbb这个属性,则浏览器直接跳过;如果使用特定的解析器打开则会对应的处理,例如读取bbb属性,获取配置的数据,用于替代标签体的原始内容,再进行显示
        原始内容
    h1>
    

模板引擎其实就是根据这种方式,使用户界面与业务数据分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档在原有的HTML页面中来填充数据。最终达到渲染页面的目的

Thymeleaf

Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本

Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。它以自然模板的概念为基础,以不影响模板用作设计原型的方式将其逻辑注入模板文件。这样可以改善设计沟通,并缩小设计团队与开发团队之间的差距

Hello Thymeleaf

1、添加依赖


<project xmlns="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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>3.0.1version>
        <relativePath/> 
    parent>
    <groupId>com.yangroupId>
    <artifactId>demo3artifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>demo3name>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>17java.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-thymeleafartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

惯例优于配置

  • resources/template目录用于存储html格式的模板文件
  • resources/static目录用于存储css、js之类的文件,如果需要还可以使用webjars

全局配置 application.properties

  • 基本上不需要添加额外配置,SpringBoot提供了默认配置
spring.thymeleaf.cache=false  # 关闭thymeleaf缓存,避免修改后一直不生效的问题;如果产品环境建议打开缓存

2、定义控制器

接收客户端请求参数username,生成问候语,跳转页面显示

@Controller
public class HelloController {
    @RequestMapping(value="hello",params = "username")
    public String sayHello(String username, Model model){
        if(username.trim().length()<1)
            username="Thymeleaf";
        String msg="Hello "+username+"!";
        model.addAttribute("msg",msg);
        return "hello";
    }
}

3、定义thymeleaf模板文件 hello.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<h2>欢迎您访问当前页面h2>
body>
html>

在html页面中添加Thymeleaf相关的语法

  • 导入thymeleaf的名称空,这个名空间用于标识Thymeleaf相关的属性,同时使浏览器不能直接识别
  • th:text可以改变当前元素里面的文本内容
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<h2 th:text="${msg}">欢迎您访问当前页面h2>
body>
html>

4、启动应用,然后再浏览器中通过URL地址[Title](http://localhost:8080/hello?username=zhangsan)访问,可以看到对应的页面

特点

  • Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果
  • Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可直接套用模板实现 JSTL、OGNL表达式效果
  • Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能

Thymeleaf基础语法

另外还有片段表达式,后面结合片段模板语法再说。
变量表达式用于访问容器上下文环境中的变量
1、首先是控制器,在控制器中使用model.addAttribute准备数据

@Controller
public class HelloController {
@GetMapping("/hello")
public String sayHello(String name, Model model){
if(!StringUtils.hasText(name))
name="Thymeleaf";
String msg="Hello "+name+"!";
model.addAttribute("msg",msg);//request.setAttribute
return "hello";
}
}

2、在页面中使用变量表达式获取controller中准备的数据 ${msg}

<h2 th:text="${msg}">原始显示内容h2>

选择变量表达式*{…}

选择变量表达式计算的是选定的对象(th:object属性绑定的对象)
首先在控制器中准备数据

@RequestMapping("/hello2")
public String hello2(Model model){
User user=new User();
user.setId(99L);
user.setUsername("name_"+99);
user.setPassword("pwd_"+99);
model.addAttribute("user",user);
return "input";
}

使用选择变量表达式实现数据的显示回填

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<form action="hello" method="post" th:object="${user}"> 在form表单上绑定一个对象
<input type="text" name="id" th:value="*{id}"/> 子标签中可以使用*{}获取该对象的
属性值
<input type="text" name="username" th:value="*{username}"/> 注意这里实际上还可
以使用${user.username}
<input type="password" name="password" th:value="*{password}"/>
form>

信息表达式#{…}

信息表达式一般用于显示静态文本,也可能需要根据需求而整体变动的静态文本放在properties文件以便维护,通过与th:text属性一起使用。信息表达式主要是用于对国际化功能的支持。所谓的国际化功能就是指,根据浏览器的编码,返回对应编码的内容的支持。
1、国际化配置文件名称命名规范:
默认名:xxx.properties
指定国家编码的名称: xxx_语言编码_国家编号.properties
2、配置SpringBoot 配置文件application.properties
注意:配置的besename就是国际化文件名字名,不需要写语言国家编号以及后缀。

## 配置国际化支持
spring.messages.basename=message

一般在properties文件中不允许出现多字节编码的内容,例如中文字符。如果出现多字节编码内容
需要通过JDK提供的命令行工具native2ascii进行转换,将【中国人民】之类的中文字符转换为
UTF-8编码的字符串【\u4e2d\u56fd\u4eba\u6c11】

3、Thymeleaf 对国际化的支持,信息表达式
标签消息表达式取值:

链接表达式@{…}

Thymeleaf模板通过@{…}表达式引入URL


<script src="../static/jslib/hello.js" th:src="@{/jslib/hello.js}">script>
<img src="../static/images/mv02.jpg" th:src="@{${imagePath}}"> 这里使用控制器传
递的参数作为路径

服务器相关配置 application.properties

spring.application.name=demo 应用名称
server.port=9000 配置服务器的端口号,默认8080
server.servlet.context-path=/test 配置上下文路径,默认/

表达式补充

Thymeleaf模板表达式中可以使用各种算术运算符和逻辑运算符。

  • 算术表达式

    123

    ,如果属性要求是表达式,不写${}则当作字符串处理;如果属性不要求表达式,则必须写${}
  • 对象导航

    Product Description

控制器准备数据–数据可以来源于数据库

@GetMapping("/hello5")
public String testExp4(Model model){
	List<User> userList=new ArrayList<>();
		for(int i=0;i<10;i++){
			User tmp=new User();
			tmp.setId(i+1L);
			tmp.setUsername("name_"+i);
			tmp.setPassword("pwd_"+i);
			userList.add(tmp);
		}
		model.addAttribute("userList",userList);
		return "hello4";
}

页面显示

<table>
<tr>
<td th:text="${userList[1].id}">001td>
<td th:text="${userList[0].username}">yanjuntd>
<td th:text="${userList[3].password}">123456td>
tr>
table>

对象实例化 

22-Jun-2023

事实上这种写法不建议,因为准备显示数据应该是控制器的职责,不应该转嫁给页面控制。如果非用不可,可以考虑使用Thymeleaf中的默认工具对象 ```html

原始内容

  • T操作符

    123456


    允许在链接表达式中添加参数 @{user(id=9527,name=${userName})}访问路径并传递参数http://localhost:8080/test/user?id=9527&name=admin

三元运算符

基本运算规则和Java一致

<p th:text="7>5?'7大':'5大'">三元运算符p>
<p th:text="${age}!=null?${age}:'age等于null'">p>
<p th:text="${age2}!=null?${age2}:'age2等于null'">p>

访问WebContext对象中的属性

Thymeleaf模板通过一些专门的表达式从模板的WebContext获取请求参数,请求,会话和应用中的属性

  • ${xxx}将返回存储在Thymeleaf模板上下文中的变量xxx或者request请求域的属性xxx,不是EL中的pageContext.findAttribute操作

控制器存储数据

@GetMapping("/hello6")
public String testServlet(Model model, >HttpServletRequest request,
HttpSession session){
model.addAttribute("msg1",new Date());
request.setAttribute("msg1",9999L);
return "hello5";
}

页面显示

Model:<b th:text="${msg1}">Model中的数据b>
<hr/>
request:<b th:text="${msg1}">request中的数据b> 如>果名称不一致,则可以使用${key}的方式访问>request.setAttribute的数据

结果显示的是model中存储的数据,
request.setAttribute的数据不能显示
目前版本中已经不允许使用#request、#session和#servletContext Caused by:
java.lang.IllegalArgumentException: The
‘request’,‘session’,‘servletContext’ and ‘response’ expression utility objects are no longer available by default for template expressions and their use is not recommended. In cases where they are really needed, they should be manually added as context variables

  • ${param.xxx}返回一个名为xxx的请求参数值,可能是多个值
  • ${session.xxx}返回一个名为xxx的HttpSession作用域中的属性
  • ${application.xxx}将返回一个名为xxx的全局ServletContext上下文作用中的属性
  • 注意:不能使用${request.msg}的写法表示获取request的attribute,在新版本中默认对象的写法
    #request、#session以及#servletContext不再支持,使用则报错

与EL表达式一样,使用${xxx}获取变量值,使用 ${对象变量名.属性名}获取JavaBean属性值。

条件判断

if和unless

只有在th:if标签条件成立才会显示标签内容,th:unless只有在条件不成立才显示标签内容,可以理解为else。
控制器传递一个数据,也可以使用表达式表示条件

@GetMapping("/hello6")
public String testIf(Model model){
model.addAttribute("msg",true);
return "hello6";
}

显示页面

<b th:if="${true}">原始显示内容b>
<b th:unless="${false}">不显示内容b>
也可以使用表达式进行判断,表达式中可以使用and or not
<b th:if="${msg > 10}">原始显示内容b>
<b th:unless="${msg <= 10}">不显示内容b>
但是>和<容易和标签混淆,所以可以使用实体字符替代。用>表示>、$lt;表示<、$ge;表示>=、
$le;表示<=、$eq;表示==、not表示非!、$neq;/$ne;表示不等于!=
<b th:if="${msg > 10}">原始显示内容b>
<b th:unless="${msg > 10}">不显示内容b>

switch语句

Thymeleaf模板也支持多路选择的switch语句结构,默认属性default可用 * 表示。

<div th:switch="${msg}"> 获取控制器传递的数据
<span th:case="18">我18岁了!span> 等值判断
<span th:case="14">我14岁了!span>
<span th:case="*">我其他岁了!span> 其他默认情形
div>

循环

Thymeleaf模板使用 th:each=“obj,iterStat:${objList}” 标签进行迭代循环,迭代对象可以是List、Set、Map或者数组等。
控制器获取数据

@GetMapping("/hello9")
public String testExp9(Model model){
List<User> userList=new ArrayList<>();
for(int i=0;i<10;i++){
User tmp=new User();
tmp.setId(i+1L);
tmp.setUsername("name_"+i);
tmp.setPassword("pwd_"+i);
userList.add(tmp);
}
model.addAttribute("userList",userList);
return "hello8";
}

页面显示

<table border="1" width="60%">
<thead>
<tr><th>用户编号th><th>用户名称th><th>用户口令th>tr>
thead>
<tbody>
<tr th:each="tmp:${userList}"> 需要哪个标签循环出现则将th:each添加在哪个标
签上,tmp是循环控制变量,${userList}获取一个集合数据
<td th:text="${tmp.id}">001td>
<td th:text="${tmp.username}">Usernametd>
<td th:text="${tmp.password}">Passwordtd>
tr>
tbody>
table>

循环状态的使用

在th:each标签中可以使用循环状态变量,该变量有如下属性:

  • index:当前迭代对象的索引序号,从0开始
  • count:当前迭代对象的索引,从1开始
  • size:迭代器对象的大小
  • current当前迭代变量
  • even/odd布尔值,当前对象索引序号是否是偶数/奇数
  • first当前循环是否是第一个
  • last当前循环是否是最后一个
<table border="1" width="60%">
<thead>
<tr><td>索引变量的使用td><th>用户编号th><th>用户名称th><th>用户口令th>
tr>
thead>
<tbody>
<tr th:each="tmp,stat:${userList}"
th:bgcolor="${stat.odd?'red':'blue'}">
<td th:text="${stat.index}+' '+${stat.count}">Indextd>
<td th:text="${tmp.id}">001td>
<td th:text="${tmp.username}">Usernametd>
<td th:text="${tmp.password}">Passwordtd>
tr>
tbody>
table>

内置表达式的功能对象

在实际Web项目开发中,经常传递列表,日期等数据,所以Thymeleaf模板提供了很多内置对象,通过#
直接访问,这些内置对象一般都通过s结尾,如dates、lists、numbers、strings等。

  • #dates:java.util.Date的功能方法类
  • #numbers: 格式化数字的功能方法类
  • #strings:字符串对象的功能类,例如contains、startWiths等
  • #objects: 对objects的功能类操作
  • #bools: 对布尔值求值的功能方法
  • #arrays:对数组的功能类方法
  • #lists、#sets和#maps: 对lists之类集合功能类方法
    字符串对象的功能类
  • ${#strings.isEmpty(key)} 判断字符串是否为空,如果为空返回 true,否则返回 false
  • ${#strings.contains(msg,‘T’)} 判断字符串是否包含指定的子串,如果包含返回 true,否则返回false
  • ${#strings.startsWith(msg,‘a’)} 判断当前字符串是否以子串开头,如果是返回 true,否则返回false
  • ${#strings.endsWith(msg,‘a’)} 判断当前字符串是否以子串结尾,如果是返回 true,否则返回false
  • ${#strings.length(msg)} 返回字符串的长度
  • ${#strings.indexOf(msg,‘h’)} 查找子串的位置,并返回该子串的下标,如果没找到则返回-1
  • ${#strings.substring(msg,13)}
    ${#strings.substring(msg,13,15)} 截取子串,用户与 jdk String 类下 SubString 方法相同
  • ${#strings.toUpperCase(msg)} 字符串转大写
  • ${#strings.toLowerCase(msg)} 字符串转小写
    针对日期类型数据进行格式化【需要记忆的】
  • ${#dates.format(key)}格式化日期,默认的以浏览器默认语言为格式化标准
  • ${#dates.format(key,‘yyy/MM/dd’)}按照自定义的格式做日期转换

Thymeleaf的常用属性

其实Thymeleaf语法的使用都是通过在html页面的标签中添加th:xxx关键字首先模板套用,其属性与
html标签基本相似。

Thymeleaf属性只有当Thymeleaf模板引擎启动的情况下,才会生效,即取代对应的HTML5属性,相反,Thymeleaf属性仅仅只是一个无用的自定义属性,因为浏览器内核不认识,因此使用Thymeleaf模板引擎可以使得前端代码和后端代码分离,当出现显示问题时,可以立即定位问题所在,是前端页面还是后台返回数据有错,这也是Thymeleaf相对于JSP的一个优势

常用属性有以下几种:

th:text是在页面中输出值 th:value 可以将一个值放入到 input 标签的 value 中

  • th:style用于修改标签的style
  • th:onclick用于修改单击事件

你可能感兴趣的:(SpringBoot,java,开发语言)