全网最全(万字整理)_SpringBoot整合ThymeLeaf

news2024/11/25 21:42:48

文章目录

  • SpringBoot整合Thymeleaf
    • 0x01_入门案例
    • 0x02_Thymeleaf视图解析简介
    • 0x03_Thymeleaf的表达式
    • 0x04_Thymeleaf的标签
      • th:text
      • th:each
      • th:object
      • th:href
      • th:action
      • th:onclick
      • th:if
      • th:value
    • 0x05_内置对象
      • `#dates`
      • `#Strings`
      • `#Numbers`
      • 域对象
    • 0x0x_补充一些概念
      • 国际化
      • Thymeleaf缓存区
      • 重定向和请求转发的区别(路径的书写问题)
      • thymeleaf内置对象列表
      • 模版引擎总结
      • 网页静态化技术

SpringBoot整合Thymeleaf

SpringBoot官方推荐使用的引擎模版是Thymeleaf

image-20221129125700690

0x01_入门案例

首先需要加入依赖:

官网有很多关于thymeleaf的配置说明,其中有几个现在需要关注:

spring.thymeleaf.prefix     默认 classpath:/templates/
spring.thymeleaf.suffix     默认 .html
spring.thymeleaf.mode       默认 HTML

第一个参数指定了前缀,或者说是解析thymeleaf模版的路径

第二个参数指定了后缀,是html格式的(这点和FreeMarker类似,但是freeMarker解析的是ftlh

除了这2个参数之外,个人觉得应该配置一下缓存:

spring:
  thymeleaf:
    cache: false # 开发时关闭缓存,不然看不到实时页面

可能在开发过程中,大家会觉得每次更改页面后,都要重新重启服务,很是麻烦与反人类,可以通过配置热启动来改善(即上面的写法:spring.thymeleaf.cache=false)

其他配置项采用默认就可以了,想要看有哪些默认项的话,可以全局打开 ThymeleafProperties.java 类。

就比如我上面说的spring.thymeleaf.prefixspring.thymeleaf.suffix这两个参数,默认值可以通过 ThymeleafProperties.java 查看。下面列出了这个类的所有属性:

    private static final Charset DEFAULT_ENCODING;
    public static final String DEFAULT_PREFIX = "classpath:/templates/";
    public static final String DEFAULT_SUFFIX = ".html";
    private boolean checkTemplate = true;
    private boolean checkTemplateLocation = true;
    private String prefix = "classpath:/templates/";
    private String suffix = ".html";
    private String mode = "HTML";
    private Charset encoding;
    private boolean cache;
    private Integer templateResolverOrder;
    private String[] viewNames;
    private String[] excludedViewNames;
    private boolean enableSpringElCompiler;
    private boolean renderHiddenMarkersBeforeCheckboxes;
    private boolean enabled;
    private final Servlet servlet;
    private final Reactive reactive;

回到入门的这个项目:

Thymeleaf 模板引擎默认会读取 resources 目录下的templates目录,这个目录是用来存放 HTML 页面的。

新建一个控制器,利用业务层来查询所有的员工:

package com.bones.controller;


import com.bones.bean.Emp;
import com.bones.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;
import java.util.Map;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author bones
 * @since 2022-11-29
 */
@Controller
@RequestMapping("/emp")
public class EmpController {
    @Autowired
    private EmpService empService;

    @RequestMapping("findAll")
    public String findAll(Map<String,Object> map){
        // 调用业务层查询所有员工
        List<Emp> empList = empService.findAll();
        map.put("empList",empList);
        return "all";
    }

}


关于业务层和持久层,因为是比较“搬砖”的操作,所以我直接用mybatis-plus生成了。

上面的controller代码中:

  • @Controller:被@Controller标记的类实际上就是个SpringMVC Controller对象,它是一个控制器类
  • @RequestMapping("/emp"),指明映射路径,要注意,上面的这个处理单元访问的URL是http://localhost:8080/emp/findAll
  • @Autowired:用来注入一个EmpService对象
  • Map<String,Object> map:用于传输给前端数据

templates/all.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1> Thymeleaf </h1>
<table>
    <tr>
        <th>索引</th>
        <th>序号</th>
        <th>总人数</th>
        <th>偶数索引?</th>
        <th>奇数索引?</th>
        <th>第一?</th>
        <th>最后?</th>
        <th>工号</th>
        <th>姓名</th>
        <th>职务</th>
        <th>上级</th>
        <th>入职日期</th>
        <th>工资</th>
        <th>补助</th>
        <th>部门号</th>
    </tr>
    <tr th:each="emp,i:${empList}">
        <td th:text="${i.index}"></td>
        <td th:text="${i.count}"></td>
        <td th:text="${i.size}"></td>
        <td th:text="${i.odd}"></td>
        <td th:text="${i.even}"></td>
        <td th:text="${i.first}"></td>
        <td th:text="${i.last}"></td>
        <td th:text="${emp.empno}"></td>
        <td th:text="${emp.ename}"></td>
        <td th:text="${emp.job}"></td>
        <td th:text="${emp.mgr}"></td>
        <td th:text="${emp.hiredate}"></td>
        <td th:text="${emp.sal}"></td>
        <td th:text="${emp.comm}"></td>
        <td th:text="${emp.deptno}"></td>
    </tr>

</table>


</body>
</html>

<html lang="en" xmlns:th="http://www.thymeleaf.org">:

为 Thymeleaf 的命名空间,通过引入命名空间就可以在 HTML 文件中使用 Thymeleaf 标签语言,用关键字 “th”来标注。

其次,可以注意一下thymeleaf对于list的遍历的语法:

<tr th:each="emp,i:${empList}">
    <td th:text="${i.index}"></td>
    <td th:text="${i.count}"></td>
    <td th:text="${i.size}"></td>
    <td th:text="${i.odd}"></td>
    <td th:text="${i.even}"></td>
    <td th:text="${i.first}"></td>
    <td th:text="${i.last}"></td>
    <td th:text="${emp.empno}"></td>
    <td th:text="${emp.ename}"></td>
    <td th:text="${emp.job}"></td>
    <td th:text="${emp.mgr}"></td>
    <td th:text="${emp.hiredate}"></td>
    <td th:text="${emp.sal}"></td>
    <td th:text="${emp.comm}"></td>
    <td th:text="${emp.deptno}"></td>
</tr>

页面效果:

image-20221129160813889

你可能好奇浏览器中是怎么解析上面的html文件的呢?

可以右键查看一下页面的元素:

image-20221129161356554

数据就好像是纯文本塞进去的一样。

0x02_Thymeleaf视图解析简介

英文官方文档3.0 http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

什么是Thymeleaf?

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

Thymeleaf 的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这一点,它建立在自然模板Natural Templates的概念之上,以不影响模板用作设计原型的方式将其逻辑注入模板文件。这改善了设计的沟通并弥合了设计和开发团队之间的差距。

什么是自然模版Natural Templates

Thymeleaf编写的HTML模板在外观和功能上仍然类似于HTML,从而使应用程序中运行的实际模板可以用作有用的设计工件。

Thymeleaf 的设计从一开始就考虑了 Web 标准——尤其是 HTML5——允许您在需要时创建完全验证的模板。

Thymeleaf 在有网和没网的环境下都可以正常工作,既能让美工在浏览器中查看页面的静态效果,也能让程序员在服务器查看带数据的动态页面效果。

这是因为Thymeleaf支持 HTML 原型,在 HTML 标签里增加额外的属性来达到模板+数据的展示方式。

浏览器在解释 HTML 的时候会忽略未定义的标签属性,所以 Thymeleaf 可以静态地运行;当有数据返回页面时,Thymeleaf 标签会动态地替换静态内容。

Thymeleaf的主要目标是将优雅的自然模板带到开发工作流程中,并将HTML在浏览器中正确显示,并且可以作为静态原型,让开发团队能更容易地协作。Thymeleaf能够处理HTML,XML,JavaScript,CSS甚至纯文本。

长期以来,jsp在视图领域有非常重要的地位,随着时间的变迁,出现了一位新的挑战者:Thymeleaf,Thymeleaf是原生的,不依赖于标签库.它能够在接受原始HTML的地方进行编辑和渲染.因为它没有与Servelet规范耦合,因此Thymeleaf模板能进入jsp所无法涉足的领域。

Thymeleaf在Spring Boot项目中放入到resources/templates中。这个文件夹中的内容是无法通过浏览器URL直接访问的(和WEB-INF效果一样),所有Thymeleaf页面必须先走控制器。

下面列出一些常用的表达式、标签、函数:

常用表达式:

  • ${...}变量表达式
  • *{...}选择表达式
  • #{...}文字表达式
  • @{...}URL 表达式
  • #maps 对象表达式

常用标签:

  • th:action 定义服务器端控制器路径。
  • th:each 循环语句
  • th:field 表单字段
  • th:href URL 链接
  • th:id div 标签中的 ID
  • th:if 条件判断
  • th:include 引入文件
  • th:fragment 定义代码片段
  • th:object 替换对象
  • th:src 图片地址
  • th:text 文本
  • th:value 属性值

常用函数:

  • #dates 日期函数
  • #lists 列表函数
  • #arrays 数组函数
  • #strings 字符串函数
  • #numbers 数字函数
  • #calendars 日历函数
  • #objects 对象函数
  • #bools 布尔函数

0x03_Thymeleaf的表达式

Thymeleaf通过标准变量表达式完成数据的展示和处理

  • 1 标准变量表达式必须依赖标签,不能独立使用
  • 2 标准变量表达式一般在开始标签中,以 th开头
  • 3 语法为: <tag th:***="${key}" ></tag>
  • 4 表达式中可以通过${}取出域中的值并放入标签的指定位置
  • 5 ${}在这里不能单独使用,必须在 th:后面的双引号里使用

对于单个变量,可以通过${...}取值。

比如现在完成这样一个场景:

用户输入想要查询的工号,可以根据这个工号查询数据,并且回显出来:

EmpController中的处理单元:

@RequestMapping("/queryAllEmpno")
public String findEmpno(Map<String,Object> map){
    List<Integer> empnoList = empService.findEmpnoList();
    map.put("empnoList",empnoList);
    return "queryEmp";
}

@RequestMapping("/queryEmpbyEmpno")
public ModelAndView queryEmpbyEmpno(Integer empno){
    ModelAndView mv = new ModelAndView();
    List<Integer> empnoList = empService.findEmpnoList();
    if (empnoList.contains(empno)){
        Emp emp = empService.findEmpByEmpno(empno);
        mv.addObject("emp",emp);
        mv.setViewName("showEmp");
        return mv;
    }else {
        mv.setViewName("invalidate");
        return mv;
    }
}

queryAllEmpno用于查询所有员工的编号,将一个list返回给前端

queryEmpbyEmpno用于查询指定编号的员工

所以对应2个页面:

queryEmp.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>请选择你想要查询的员工编号</h1>
<ul th:each="empno:${empnoList}">
    <li th:text="${empno}"></li>
</ul>
<form action="/emp/queryEmpbyEmpno" method="POST">
    <h3>请填写你想要查询的员工编号:</h3>
    <input type="text"  name="empno">
    <input type="submit" value="查询">
</form>
</body>
</html>

这里涉及遍历list集合的语法:

<ul th:each="empno:${empnoList}">
    <li th:text="${empno}"></li>
</ul>

以及提交数据给后端:

<form action="/emp/queryEmpbyEmpno" method="POST">
    <h3>请填写你想要查询的员工编号:</h3>
    <input type="text"  name="empno">
    <input type="submit" value="查询">
</form>

showEmp.html展示查询结果:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        table,th,td,th{
            border: 1px solid forestgreen;
            border-collapse: collapse;
        }
    </style>
</head>
<body>
<h2>
    查询成功:
</h2>

<table>
    <tr>
        <th>员工编号</th>
        <th>员工姓名</th>
        <th>员工入职日期</th>
        <th>员工上级</th>
        <th>员工职位</th>
        <th>员工薪资</th>
        <th>员工补助</th>
        <th>员工所属部门编号</th>
    </tr>
    <tr>
        <td th:text="${emp.empno}"></td>
        <td th:text="${emp.ename}"></td>
        <td th:text="${emp.hiredate}"></td>
        <td th:text="${emp.mgr}"></td>
        <td th:text="${emp.job}"></td>
        <td th:text="${emp.sal}"></td>
        <td th:text="${emp.comm}"></td>
        <td th:text="${emp.deptno}"></td>
    </tr>
</table>
<a th:href="@{/emp/queryAllEmpno}">
    返回
</a>
</body>
</html>

并且有一个链接<a th:href="@{/emp/queryAllEmpno}">返回</a>可以回到刚才的页面。

除此之外,还有一个提示用户输入信息有攻击性行为,提示用户回到首页的html页面:

invalidate.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>您的行为存在攻击行为,建议您回到首页!</h1>
<a th:href="@{/index}">回到首页</a>
</body>
</html>

这个页面也有th:href="@{}"表达式:th:href="@{/index}

请求的是后台这个处理单元:

MainController:(这个controller的命名是我随便取的,可能不是很符合规范)

package com.bones.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {
    @RequestMapping("/index")
    public String index(){
        return "index";
    }
}

以上总结了2个表达式的使用:

  • ${}:用于访问容器上下文环境中的变量,功能同jstl${}
  • @{}:超链接url表达式。

另外还有几个表达式:

  • #{}:消息表达式(井号表达式,资源表达式)。通常与th:text属性一起使用,指明声明了th:text的标签的文本是#{}中的key所对应的value,而标签内的文本将不会显示。(消息表达式#{…}主要用于Thymeleaf模板页面国际化内容的动态替换和展示。)
  • *{}:选择表达式(星号表达式)。选择表达式与变量表达式有一个重要的区别:选择表达式计算的是选定的对象,而不是整个环境变量映射。也就是:只要是没有选择的对象,选择表达式与变量表达式的语法是完全一样的。那什么是选择的对象呢?是一个:th:object对象属性绑定的对象。

下面练习这两个表达式,不过首先要注意:查看并修改ideafiles encoding ,修改为UTF-8、勾选自动转为ascii码(防止修改完成后页面出现乱码)

除此之外,如果下面的例子还有乱码就要参考:

https://blog.csdn.net/sunp_csdn/article/details/122821197

以及关于国际化的知识来解决:https://blog.csdn.net/qq_43437874/article/details/118840835

还要注意的是,在application.yaml中要正确配置:

spring:
  # 模版引擎thymeleaf
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  # 数据源
  datasource:
    username: XXXX
    password: XXXX
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver
  messages:
    basename: i18n/msg

上面spring.messages.basename默认值为messages,根据properties的位置修改为:i18n

│   │   └── resources
│   │       ├── application.yaml
│   │       ├── i18n
│   │       │   ├── msg.properties
│   │       │   ├── msg_en_US.properties
│   │       │   └── msg_zh_CN.properties

这里附上一张图:

image-20221130222215107

express.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>i18n</h1>
<h1 th:text="#{name}"></h1>
<a  th:href="@{/msg(lang='zh_CN')}">中文</a>
<a  th:href="@{/msg(lang='en_US')}">English</a>

</body>
</html>

关于*{}表达式的使用,这里再举一个例子:(下面再实体类上面的注解是Lombok)

首先是2个实体类:Role

package com.bones.bean;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Role {
    private Long roleId;
    private String roleName;
}

User

package com.bones.bean;

import lombok.Builder;
import lombok.Data;

import java.util.Date;

@Data
@Builder
public class User {
    private String username;
    private String password;
    private Integer age;
    private Date birthday;
    private String email;
    private Double money;
    private Role role;
}

然后是控制层UserController的请求单元:

package com.bones.controller;

import com.bones.bean.Role;
import com.bones.bean.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Date;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/getUser")
    public String getUser(Model model){
        //添加User信息(包括Role信息)
        Role role = Role.builder().roleId(1L).roleName("admin").build();
        User user = User.builder().role(role).username("张三").password("123456").age(23).birthday(new Date()).build();
        model.addAttribute("user",user);
        return "showUser";
    }
}

页面:showUser.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1> Thymeleaf 表达式*{}的用法 </h1>

<div th:object="${user.role}">
    <p th:text="*{roleName}"></p>

</div>

</body>
</html>

页面效果:

image-20221130234548943

*{}:选择表达式,是选定的对象,不是整个环境的映射。如果没对象,和变量表达式${} 基本上没区别

0x04_Thymeleaf的标签

上面的多个例子中涉及了多个标签,比如:

th:text

上面练了很多次了,不多说

补充一下三目运算符:

th:text="${emp.ename eq 'KING'}?大boss:删除"

th:each

数据迭代,取出域中的数据(数组/集合)去进行循环,通常配合**th:text="${x1.x3}"**使用

th:object

(和*{}一起使用)

th:href

比如th:href="@{x1(x2=${x3.x4})}"

x1为超链接指向的路径;x2为自己命名的名称;x3,x4为上边数据迭代中的**th:text=“${x1.x3}”**x1和x3.

<a th:href="@{/goods/doDeleteById(id=${g.id})}">
delete
</a>

关于超链接指向地址,还提供了restful风格的写法,
平时我们所写代码地址上带请求数据一般为:a/b/c?id=x
而restful这种风格为:a/b/c/{id}

<a th:href="@{/goods/doFindById/{id}(id=${g.id})}">
update
</a>

在这种语法中,{id}为一个变量表达式,由后面()内的内容补充,如果我们希望在后端的Controller类的方法参数中获得传递的参数,就需要加@PathVariable描述参数.

除此以外,还有以下标签,依次举例说明:

th:action

提交表单,语法:th:action="@{x1}",x1为表单所要提交至的地址.

比如随便写个登录框:

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1> 登录 </h1>
<form th:action="@{/loginUser}" method="post">
    用户名:<input type="text" name="username" >
    密码:<input type="password" name="password" >
    <p>
        <input type="submit" value="登录">
    </p>
</form>
</body>
</html>

后台处理单元:

@PostMapping("/loginUser")
public String loginUser(String username, String password, Model model){
    model.addAttribute("username",username);
    return "success";
}

success页面:

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    欢迎您
    <span th:text="${username}"></span>
</h1>
</body>
</html>

th:onclick

点击事件

举例:点击“删除”,会删除数据库中的数据:

image-20221201140137628

前端all.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1> Thymeleaf </h1>
<table>
    <tr>
        <th>索引</th>
        <th>序号</th>
        <th>总人数</th>
        <th>偶数索引?</th>
        <th>奇数索引?</th>
        <th>第一?</th>
        <th>最后?</th>
        <th>工号</th>
        <th>姓名</th>
        <th>职务</th>
        <th>上级</th>
        <th>入职日期</th>
        <th>工资</th>
        <th>补助</th>
        <th>部门号</th>
        <th>操作</th>
    </tr>
    <tr th:each="emp,i:${empList}">
        <td th:text="${i.index}"></td>
        <td th:text="${i.count}"></td>
        <td th:text="${i.size}"></td>
        <td th:text="${i.odd}"></td>
        <td th:text="${i.even}"></td>
        <td th:text="${i.first}"></td>
        <td th:text="${i.last}"></td>
        <td th:text="${emp.empno}"></td>
        <td th:text="${emp.ename}"></td>
        <td th:text="${emp.job}"></td>
        <td th:text="${emp.mgr}"></td>
        <td th:text="${emp.hiredate}"></td>
        <td th:text="${emp.sal}"></td>
        <td th:text="${emp.comm}"></td>
        <td th:text="${emp.deptno}"></td>
        <td>
            <a href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]])">删除</a>
        </td>
    </tr>

</table>


</body>
</html>
<script>
    function removeEmp(empno){
        var conf = confirm("请问是否删除员工编号为"+empno+"的信息?")
        if (conf){
            window.location.href = "removeEmp?empno="+empno;
        }

    }
</script>

后台处理单元:

@RequestMapping("/removeEmp")
public String removeEmp(Integer empno){
    System.out.println(empno);
    empService.removeEmpByEmpno(empno);
    return "forward:/emp/findAll";
}

其他JS的事件也类似,onblur,onfocus等等方法。

th:if

现在完成一个功能,名为KING的员工是大老板,不能删除。

在上面的例子中只需要这么修改即可:

<a th:if="${!(emp.ename eq 'KING')}" href="javascript:void(0)" th:onclick="removeEmp([[${emp.empno}]])">删除</a>

加了:th:if="${!(emp.ename eq 'KING')}",此时,只要满足条件,就会显示a标签。

页面效果:(可以看到KING的删除a标签没了)

image-20221201141120624

th:value

表单元素,设置HTML标签中表单元素value属性时使用。


常用的标签基本展示完毕,其实还有很多,用到了还可以再另外学。

0x05_内置对象

Thymeleaf提供了一些内置对象,内置对象可直接在模板中使用。这些对象是以#引用的。

使用内置对象的语法

1引用内置对象需要使用#

2大部分内置对象的名称都以s结尾。如:strings、numbers、dates
3常见内置对象如下

#arrays:数组操作的工具;

#aggregates:操作数组或集合的工具;

#bools:判断boolean类型的工具;

#calendars:类似于

#dates,但是是java.util.Calendar类的方法;

#ctx:上下文对象,可以从中获取所有的thymeleaf内置对象;

#dates:日期格式化内置对象,具体方法可以参照java.util.Date;

#numbers: 数字格式化;#strings:字符串格式化,具体方法可以参照String,如startsWith、contains等;

#objects:参照java.lang.Object;

#lists:列表操作的工具,参照java.util.List;

#sets:Set操作工具,参照java.util.Set;

#maps:Map操作工具,参照java.util.Map;

#messages:操作消息的工具。

更多的内置对象,可以通过package org.thymeleaf.expression包下都有对应的类查看:

image-20221201142906467

这里主要来看域对象,Strings,Numbers,Dates

#dates

常用方法有

${#dates.format(date)}
${#dates.format(date, 'dd/MMM/yyyy HH:mm')}

举例:

<td th:text="${#dates.format(emp.hiredate,'YYYY-MM-dd')}"></td>

#Strings

常用方法有:

${#strings.isEmpty(name)}
${#strings.contains(name,'ez')} 
${#strings.containsIgnoreCase(name,'ez')} 
${#strings.startsWith(name,'Don')}
${#strings.endsWith(name,endingFragment)} 
${#strings.indexOf(name,frag)} // also array*, list* and set*
${#strings.substring(name,3,5)} // also array*, list* and set*
${#strings.substringAfter(name,prefix)} // also array*, list* and set*
${#strings.substringBefore(name,suffix)} // also array*, list* and set*
${#strings.replace(name,'las','ler')} // also array*, list* and set*
${#strings.prepend(str,prefix)} // also array*, list* and set*
${#strings.append(str,suffix)} // also array*, list* and set*
${#strings.toUpperCase(name)} // also array*, list* and set*
${#strings.toLowerCase(name)} // also array*, list* and set*
${#strings.trim(str)} // also array*, list* and set*
${#strings.length(str)} // also array*, list* and set*
${#strings.equals(first, second)}
${#strings.equalsIgnoreCase(first, second)}
${#strings.concat(values...)}
${#strings.concatReplaceNulls(nullValue, values...)}

举例:查询名字中包含“E”的员工

<tr th:each="e:${empList}" th:if="${#strings.contains(e.ename,'E')}" >
    <td th:text="${e.empno}"></td>
    <td th:text="${e.ename}"></td>
    <td th:text="${e.job}"></td>
    <td th:text="${e.mgr}"></td>
    <td th:text="${e.hiredate}"></td>
    <td th:text="${e.sal}"></td>
    <td th:text="${e.comm}"></td>
    <td th:text="${e.deptno}"></td>
</tr>

#Numbers

常用方法:

${#numbers.formatInteger(num,3)}
${#numbers.formatInteger(num,3,'POINT')}
${#numbers.formatDecimal(num,3,2)}
${#numbers.formatDecimal(num,3,2,'COMMA')}
${#numbers.sequence(from,to)}
${#numbers.sequence(from,to,step)}

举例:

#numbers.formatDecimal(numbwe,整数位,整数位千分位标识符,小数位,小数位表示符)

${#numbers.formatDecimal(num,1,'COMMA',2,'POINT')}

显示:99,999,999.99
${#numbers.formatDecimal(num,0,'COMMA',2,'POINT')}则显示 .00

${#numbers.formatDecimal(num,1,'COMMA',2,'POINT')}则显示 0.00

COMMA:','(逗号)

POINT:‘.’(点)

域对象

三个域:request,session,application(servletContext)

用法:

request:<br/>
<span th:text="${#httpServletRequest.getAttribute('msg')}"></span><br/>
<span th:text="${#request.getAttribute('msg')}"></span><br/>
<span th:text="${msg}"></span><br/>
session:<br/>
<span th:text="${#httpSession.getAttribute('msg')}"></span><br/>
<span th:text="${#session.getAttribute('msg')}"></span><br/>
<span th:text="${session.msg}"></span><br/>
application:<br/>
<span th:text="${#servletContext.getAttribute('msg')}"></span><br/>
<span th:text="${application.msg}"></span><br/>

0x0x_补充一些概念

国际化

国际化,也叫 i18n,为啥叫这个名字呢?因为国际化英文是 internationalization ,在 i 和 n 之间有 18 个字母,所以叫 i18n。我们的应用如果做了国际化就可以在不同的语言环境下,方便的进行切换,最常见的就是中文和英文之间的切换,国际化这个功能也是相当的常见。

在 Spring 中,就通过 AcceptHeaderLocaleResolver 对国际化提供了支持,开发者通过简单配置,就可以在项目中直接使用国际化功能了。

这一支持,在 Spring Boot 中得到进一步的简化,在 Spring Boot 中,我们也可以通过寥寥数行代码就能方便的实现国际化功能,接下来松哥就来和大家说一说 Spring Boot 中的国际化。

项目中的国际化我们往往需要多方面的支持,例如后端做国际化、前端页面也要做国际化,共同搭配,才能真正实现国际化的功能。

Thymeleaf缓存区

还记得之前提到的在application.yaml中提到的配置吗?

spring:
  # 模版引擎thymeleaf
  thymeleaf:
    cache: false

cache是thymeleaf带有的一个缓存区,我们将它设置为false即可不需要每次重启服务,直接刷新界面就可以(但要注意服务端的代码修改的话还是需要重启服务器)

但也不要一味的认为cache的设置就是麻烦的,它主要的作用是要在项目上线时设置为true(不设置默认为true),这样它会提供一个缓存区,不用每次都向服务器请求数据,可以有效的提高响应速度.

重定向和请求转发的区别(路径的书写问题)

其实这个在学习JSP/Servlet的时候一定会接触:

1)当我们的url地址没有以"/“开头时,默认这个内容要替换到现在地址栏url最后一个”/"后的内容进行拼接.

2)请求转发:return “forward:doGoodsUI”;
重定向:return “redirect:/goods/doGoodsUI”;
请求转发由于是服务端内部转发所以可以不写"/“,直接跳转;
而重定向由于是二次请求二次响应,且可以跳转至别的资源甚至是别的服务器,所以需要写绝对地址,必须以”/"开头!

thymeleaf内置对象列表

见链接:https://www.jianshu.com/p/a1a677c2599b

模版引擎总结

3种模版引擎:JSP,FreeMarker,Thymeleaf

jsp

优点:

1、功能强大,可以写java代码

2、支持jsp标签(jsp tag)

3、支持表达式语言(el)

4、官方标准,用户群广,丰富的第三方jsp标签库

缺点:

性能问题。不支持前后端分离

freemarker

FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

目前企业中:主要用Freemarker做静态页面或是页面展示

优点:

1、不能编写java代码,可以实现严格的mvc分离

2、性能非常不错

3、对jsp标签支持良好

4、内置大量常用功能,使用非常方便

5、宏定义(类似jsp标签)非常方便

6、使用表达式语言

缺点:

1、不是官方标准

2、用户群体和第三方标签库没有jsp多

Thymeleaf

Thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用。

Thymeleaf的主要目标在于提供一种可被浏览器正确显示的、格式良好的模板创建方式,因此也可以用作静态建模。你可以使用它创建经过验证的XML与HTML模板。相对于编写逻辑或代码,开发者只需将标签属性添加到模板中即可。接下来,这些标签属性就会在DOM(文档对象模型)上执行预先制定好的逻辑。Thymeleaf的可扩展性也非常棒。你可以使用它定义自己的模板属性集合,这样就可以计算自定义表达式并使用自定义逻辑。这意味着Thymeleaf还可以作为模板引擎框架。

优点:静态html嵌入标签属性,浏览器可以直接打开模板文件,便于前后端联调。springboot官方推荐方案。

缺点:模板必须符合xml规范

除此以外,现在的趋势是前后端分离,比如前端用VUE。

网页静态化技术

FreeMarker用于网页静态化技术最多。

使用方法将页面转换成静态页面的过程(本文主要介绍了其中的一种:模板技术(FreeMarker))

页面静态化是以空间换时间的方式,在添加和修改对象时就生成静态页面,访问时实际访问的是一个静态页面

优点

  • (1)降低查询数据库的次数,减轻数据库的压力,从而提高查询效率
  • (2)响应速度快,可以提高用户的体验

页面静态化的编程步骤

(1)导入FreeMarker.jar

(2)获取模板(Template)对象

(3)准备数据

(4)template.process() 生成静态资源

(5)创建xxx.ftl静态化页面模板

(6)测试运行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52846.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

01-09-hive-入门基本概念-hive-mysql安装

01-hive-入门基本概念&#xff1a; 什么是hive hive是基于Hadoop的一个数据仓库工具&#xff0c;用来进行数据提取、转化、加载&#xff0c;这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表&#xf…

算法竞赛入门【码蹄集进阶塔335题】(MT2271-2275)

算法竞赛入门【码蹄集进阶塔335题】(MT2271-2275&#xff09; 文章目录算法竞赛入门【码蹄集进阶塔335题】(MT2271-2275&#xff09;前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f;目录1. MT2271 完全立方数32. MT2272 质数率3. MT2273 元素共…

如何修复 Windows 11/10上的 0x8007023e Windows 更新错误

修复 0x8007023e 错误 运行 Windows Update 疑难解答重置 Windows Update 组件使用 DISM 工具修复 Windows Update 客户端从 Microsoft update Catalog 网站下载并安装更新运行 Microsoft 支持和恢复助手系统更新根据 Windows 质量更新服务节奏发布到 Windows 设备。如果当您尝…

zookeeper学习(一)zk特性与节点数据类型详解(2022)

Zookeeper是一个开源的分布式协调框架&#xff0c;主要用来解决分布式集群中应用系统的一致性问题。从设计模式角度来理解其实zk是一个基于观察者模式设计的分布式服务管理框架。 CAP理论&#xff1a; cap理论指出对于一个分布式计算系统来说&#xff0c;不可能同时满足以下三…

COMSOL泰森多边形Voronoi图多孔骨架优化模型受力分析

Voronoi模型 在comsol内建立泰森多边形骨架支撑网格&#xff0c;模型采用一般的多边形泰森多边形孔隙以及样条曲边泰森多边形孔隙做对比研究&#xff0c;分析模型在承受压力荷载下的应力分布。通过comsol的固体力学计算可看出拟圆形Voronoi孔隙支撑结构的应力分布更为合理&…

【LIMU-Bert论文阅读】

LIMU-BERT: Unleashing the Potential of Unlabeled Data for IMU Sensing Applications 题目重点&#xff1a; 充分利用无标签数据适用于IMU传感器应用&#xff08;并没有指出specfic task&#xff09; 文章核心&#xff1a; 如何根据IMU数据的特征设计出LIMU-Bert&#xff0c…

基于模糊逼近系统不确项的滑模自适应控制

目录 前言 1.系统描述 2.控制器设计 3.模糊推理估计不确定f 3.1构造模糊系统 3.2模糊推理过程 3.3 自适应律设计 4.仿真分析 4.1仿真模型 4.2仿真结果 5.总结 前言 在一般的建模仿真中&#xff0c;我们假设模型都是可以用数学模型描述出来的是确定的&#xff0c;称…

1. 一些截图方法的比较;2. 将截图直接转换为PDF并拼接,与插入Word后再转换为PDF的对比

1. 一些截图方法的比较 1.1. 有时候当某个软件没有导出功能&#xff0c;或者导出功能受限&#xff0c;比如 tableau public&#xff0c;但又需要获取展示出的可视化信息时&#xff0c;就需要用到截图。如果这些截图还要用在正式文档中&#xff0c;就需要是高清的&#xff0c;至…

Python预测卡塔尔世界杯身价最高的英格兰要夺冠?!

文章目录&#x1f3f3;️‍&#x1f308; 1. 数据&#x1f3f3;️‍&#x1f308; 2. 绘图2.1 绘制表头2.2 绘制排名、球队以及国旗2.3 绘制身价柱状图2.4 绘制FIFA排名散点图2.5 设置背景2.6 设置标题&#x1f3f3;️‍&#x1f308; 3. 更多可视化项目源码数据&#xff1a;大…

关于 find 命令的15个超级有用的例子

find 命令用于在 Linux 命令行中搜索文件和目录。 find 是功能最强大、使用最频繁的命令之一&#xff0c;同时也是选项最多的命令之一&#xff0c;它有50多个选项&#xff0c;很容易让人弄混了&#xff0c;特别是当它与 exec 或 xargs 命令一起使用的时候。 作为系统管理员或…

AI创作教程之 如何在本地 PC 上运行稳定的 Diffusion 2.0 (无代码指南)

AI 的热门图像生成器 Stable Diffusion日前发布了全新的 2.0版本。新版本比以前的版本带来了许多进步和改进。OpenCLIP 中新的深度检测和更好的文本到图像模型是我最兴奋的功能。 查看本文以查看 SD 2.0 中新增功能的完整列表。 在本文中,我将向您展示如何在本地 PC 上试用新…

PHP基于thinkphp的在线教学网站#毕业设计

在线教学系统采用B/S模式&#xff0c;促进了在线教学系统的安全、快捷、高效的发展。传统的管理模式还处于手工处理阶段&#xff0c;管理效率极低&#xff0c;随着用户的不断增多&#xff0c;传统基于手工管理模式已经无法满足当前用户需求&#xff0c;随着信息化时代的到来&am…

DataFrame API入门操作及代码展示

文章目录DataFrame风格编程DSL风格编程代码示例相关API相关代码示例SQL风格编程代码示例相关API相关代码Fucntions包基于SparkSQL的WordCount代码编写DataFrame风格编程 DataFrame支持两种风格进行编程 DSL风格SQL风格 DSL称之为领域特定语言&#xff0c;其实就是指DataFrame特…

Config配置文件读写

配置文件本质上是包含成功操作程序所需信息的文件&#xff0c;这些信息以特定方式构成。它们不是在程序中进行硬编码&#xff0c;而是用户可配置的&#xff0c;通常存储在纯文本文件中。 写配置文件 使用函数WritePrivateProfileStringW写配置文件 BOOL WritePrivateProfile…

filter: grayscale(1); | 网页变灰

效果 MDN: https://developer.mozilla.org/zh-CN/docs/Web/CSS/filter-function/grayscalegrayscale(amount)对图片进行灰度转换转换值的大小&#xff0c;可以是 或 . 当值为 100% 时&#xff0c;灰度最大。0% 时与原图没有区别。0% 到 100% 之间的值会使灰度线性变化。amount …

JVM学习笔记(2)—— 运行时数据区概述及线程

在上一篇中我们讲了JVM的类加载子系统&#xff0c;现在我们就来到了运行时数据区。而不同版本的JVM对于内存的划分方式和管理机制存在着部分差异&#xff08;最典型的就是方法区实现的差异&#xff09;&#xff0c;本文针对经典的Hotspot jvm进行讨论&#xff0c;对运行时数据区…

Mongoose应用和文件上传

一、Express框架访问MongoDB数据库 1、目的&#xff1a; ​ &#xff08;1&#xff09;mongoose模块的使用 ​ &#xff08;2&#xff09;学会代码的封装&#xff1a;dao层、service层、接口层 ​ &#xff08;3&#xff09;MVC设计思想&#xff1a;M(Model)、V(View)、C(C…

WEB前端期末大作业——关于酒店主题网站设计——高级酒店公寓网页(4页)

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

如何使用gitee码云?创建库,克隆远程仓库,上传代码,小绿格等问题

目录 前提软件&#xff1a;先安装Git&#xff0c;再安装TortoiseGit&#xff08;可以在网上找找~默认下一步安装即可&#xff09; 一、访问网站Gitee - 基于 Git 的代码托管和研发协作平台 二、创建库 二、克隆远程仓库到本地电脑 - 仓库与本地链接 三、上传文件到gitee库里…

【Linux基础知识点】内核、系统调用、Shell、指令集、微架构、硬件架构、用户态、内核态、进程、用户线程、内核线程

参考 Linux内核版本和发行版本Linux架构用户态和内核态的简单理解「建议收藏」CPU、操作系统内核、ARM内核与架构的理解【科普】一文看懂指令集是什么一文搞懂X86架构和ARM架构的区别线程和进程的区别是什么&#xff1f;如何理解内核线程、内核进程&#xff1f; 讲解 知识点详…