1. 概述
Thymeleaf是一款优秀的JAVA模板引擎。该引擎工作在服务端,能够处理HTML、XML、JavaScript、css甚至纯文本。Thymeleaf拥有良好的扩展性,与其他流行的模板引擎(例如JSP)相比,拥有更快的开发效率,特别是在团队合作开发中。
本文将阐述如何在Spring MVC应用中的视图层中使用Thymeleaf模板引擎。
2. Thymeleaf与Spring集成
Thymeleaf能够非常轻松的与Spring结合在一起,在Spring MVC项目中,只需要引入依赖spring boot提供的Thymeleaf即可:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
如果你没有使用Spring Boot,则可参考官方文档进行配置。当然了,那将比使用Spring Boot麻烦的多。
3. 显示多语言文件(Message Source)中的值
th:text=”#{key}”标签可以显示多语言文件中的值。Spring Boot项目默认加载messages多语言系列源。若加载自定义的多语言源,则可以参考以下实现:
/** * 手动注册多国语言文件messages * Spring Boot其实已经默认注册了messages,所以删除该方法后不会对应用造成影响 * 在此的代码仅做演示用 * * @return */ @Bean public ResourceBundleMessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); messageSource.setBasename("messages"); messageSource.setDefaultEncoding("UTF-8"); return messageSource; }
在Thymeleaf模板中,便可如下使用:
<h1 th:text="#{welcome}"></h1>
则H1中的值将根据当前用户的地区及语言,对应显示不同的内容。比如对简体中文用户显示“您好”,而对英文用户显示"welcome"。
4. 显示模型属性
4.1 简单属性
th:text=”${attributename}”用于显示模型model上的属性。比如我们在模型上添加当前用户currentUser:
model.addAttribute("currentUser", "zhangsan");
则在Thymeleaf模板中可以如下显示:
<h2 th:text="${currentUser}"></h2>
4.2 集合Collection属性
如果model上的某个属性类型为集合Collection,则可以使用th:each来达到遍历集合的目的。比如有学生Student类有如下字段:
public class Student { private Long id; private String name; private Boolean sex; // 省略getter/setter
控制器中绑定如下:
List<Student> students = new ArrayList<>(); for (int i = 0; i < 10; i++) { students.add(new Student(Long.valueOf(i), "name" + i, i % 2 == 0)); } model.addAttribute("students", students);
则在Themeleaf模板中如下进行遍历:
<tr th:each="student: ${students}"> <td th:text="${student.id}"></td> <td th:text="${student.name}"></td> </tr>
5. 条件判断
5.1 if以及unless
th:if=”${condition}”用以当condition成立时进行显示。相反的th:unless=”${condition}” 用以当condition不成立时显示。
比如我们可以如下显示性别:
<td th:if="${student.sex}" th:text="男"></td> <td th:unless="${student.sex}" th:text="女"></td>
5.2 switch以及case
th:switch和th:case的用法当然也不能理解,比如可以使用switch、case如下显示性别:
<td th:switch="${student.sex}"> <span th:case="true" th:text="男"></span> <span th:case="false" th:text="女"></span> </td>
6. 处理输入
Form表单输入可以使用 th:action=”@{url}”以及th:object=”${object}” 轻松完成。th:action用于表示Form表单的提交地址,th:object用以标注Form表单绑定的对象。在表单中直接使用th:field=”*{name}” 来绑定表单中的字段,其中name关键字与object上的属性相对应。比如新建如下添加学生表单:
<form action="#" th:action="@{/student/save}" th:object="${student}" method="post"> <table border="1"> <tr> <td>ID</td> <td><input type="number" th:field="*{id}"/></td> </tr> <tr> <td>姓名</td> <td><input type="text" th:field="*{name}"/></td> </tr> <tr> <td><input type="submit" value="提交"/></td> </tr> </table> </form>
上述代码中th:action上的/student/save标明了该表单的提交地址,th:object上的student则是该表单绑定的对象。
然后在C层中可以如下接收:
@PostMapping("save") String save(Student student) { // 处理新增学生逻辑 }
7. 显示校验信息
借助于spring-boot-starter-validation,可以轻松的完成输入数据的校验工作:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
在C层中完成校验仅仅需要加入@Valid注解以及注入BingdingResult:
@PostMapping("save") String save(@Valid Student student, BindingResult errors) { if (errors.hasErrors()) { return "student/add"; } // 具体持久化学生的代码略过 return "redirect:/student/success"; }
在模板中,可以使用#fields.hasErrors()方法来获取是否发生校验错误;使用#fields.hasErrors(final String field), #fields.errors(final String field)方法来更精确到获取到某个字段是否发生校验错误;使用th:errors 属性来显示具体的错误信息:
<tr> <td>ID</td> <td><input type="number" th:field="*{id}"/></td> <td th:if="${#fields.errors('id')}" th:errors="*{id}">id校验信息</td> </tr> <tr> <td>姓名</td> <td><input type="text" th:field="*{name}"/></td> <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}">name校验信息</td> </tr>
此外#fields.errors()还可以接收*或all做为参数值,表示:发生的所有的错误的集合。比如实现遍历错误信息并依次输出:
<h1 th:if="${#fields.hasErrors()}">发生错误</h1> <ul> <li th:each="err : ${#fields.errors('*')}" th:text="${err}"/> </ul>
或者:
<li th:each="err : ${#fields.errors('all')}" th:text="${err}"/>
或者传入global来获取全局的错误信息:
<li th:each="err : ${#fields.errors('global')}" th:text="${err}" />
8. 数据转换
在Thymeleaf模板中,可以使用{{}}来格式化输出字段。比如我们在输出学生姓名name时,将首字母进行大写,则可以建立实现Formatter接口的如下NameFormatter:
/** * 名称首写字大写转换器 */ public class NameFormatter implements Formatter<String> { @Override public String parse(String s, Locale locale) throws ParseException { if (s != null && !s.isEmpty()) { return s.toUpperCase().charAt(0) + s.substring(1); } return ""; } @Override public String print(String s, Locale locale) { return s; } }
并于配置文件中注册该转换器:
@Configuration public class SpringWebConfig implements WebMvcConfigurer { /** * 注册转换器 * * @param registry 转换器注册商 */ @Override public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new NameFormatter()); }
然后便可以在模板中引入{{}}使得Thymeleaf自动调用该转换器了:
<td th:text="${{student.name}}"></td>
除按字段名进行转换外,还支持按类型进行转换。比如我们新建如下StudentFormatter用以显示Student类型:
/** * 学生实体 转换器 */ public class StudentFormatter implements Formatter<Student> { /** * 将字符串转换为Student实体 * 本例中未使用该方法,直接抛出异常 * * @param text 字符器 * @param locale 地区 * @return * @throws ParseException */ @Override public Student parse(String text, Locale locale) throws ParseException { throw new RuntimeException("方法未实现"); } /** * 将学生实体转为输出的字符串 * @param student 学生 * @param locale 地区 * @return */ @Override public String print(Student student, Locale locale) { return student.getId().toString() + "-" + (student.getSex() ? "男" : "女") + "-" + student.getName(); } }
注册如下:
@Override public void addFormatters(FormatterRegistry registry) { registry.addFormatterForFieldType(Student.class, new StudentFormatter()); registry.addFormatter(new NameFormatter()); }
便可在模板中使用如下代码来显示学生的整体信息:
<td th:text="${{student}}"></td>
最后,还可以使用#conversions 模板中将对象的进行强制转换。#conversions.convert(Object, Class)语法表示将Object转换为Class类型。比如我们将性别sex字段由Boolean类型转换为String类型:
<td th:text="${#conversions.convert(student.sex, 'String')}"></td>
9. 总结
本文对Spring MVC应用集成Thymeleaf模板引擎进行了简单的介绍。Thymeleaf模板引擎可以基于Spring MVC快速的创建应用程序,数据绑定方式灵活、易用。
最后,我们一如既往的为本文提供了完整、可运行的code demo,希望能对你有所帮助。