Thymeleaf是用于Web和独立环境的服务器端Java模板引擎。它能够处理HTML、XML、JavaScript、CSS甚至纯文本。
Thymeleaf的主要目标是提供一种简洁的,具有更好可维护性的创建模板的方法。为了实现这一点,它基于自然的模板概念,在不影响被当做设计原型的模板的前提下,将它的逻辑注入到模板文件中。这样既改善了设计上的沟通,也弥合了设计与开发团队间的分歧。
Thymeleaf从一开始设计时就考虑到了Web标准--尤其是HTML5--如果需要的话,可以创建完全校验的模板。
Thymeleaf可以处理6种模板,每种模板都称为模板模式:
HTML,XML,TEXT,JAVASCRIPT,CSS,RAW。
有两种标记模板模式(HTML和XML),三种文本模板模式(TEXT,JAVASCRIPT和CSS)和一种无操作模板模式(RAW),每种类型都被称为一种模板模式。
- HTML模板模式可以是任何类型的HTML,包括HTML5,HTML4和XHTML。这种模式不会做内容验证或格式检查,并且模板代码/结构在输出时尽可能保持原样。
- XML模板模式允许XML格式的输入。这样,代码格式必须是完整的--不允许未闭标签和未加引号的属性,如果格式错误,解析器会抛出异常。注意,不会对DTD或XML Schema验证。
- TEXT模板模式可对非标记性质的模板使用特殊语法。例如,文本电子邮件或模板化文档。注意,HTML或XML模板也可作为TEXT处理,在这种情况下,它们不会被解析为标记,而每个tag,DOCTYPE,注释等都被视为纯文本。
- JAVASCRIPT模板模式允许处理Thymeleaf应用程序中的JS文件。这意味着能像在HTML文件中那样在JS文件中使用模型数据,但要使用JS特有的集成方式,比如特殊转义(specialized escaping)或自然脚本(natural scripting)。JAVASCRIPT模板模式被看成是文本模式,因此使用与文本模板模式相同的特定语法。
- CSS模板模式允许处理Thymeleaf应用程序中涉及的CSS文件。类似于JAVASCRIPT模式,CSS模板模式也是文本模式,并使用TEXT模板模式中的特殊处理语法。
- RAW模板模式根本不会处理模板。它的作用是将未处理的资源(文件、URL响应等)插入正在处理的模板中。例如,可将HTML格式外部的、不受控制的资源包含到应用程序模板中,并且尽可能地让这些资源包含的任何Thymeleaf代码都不会被执行。
Thymeleaf是一个极具扩展性的模板引擎(实际上,它可以被称为模板引擎框架),它允许定义和定制模板处理的方式,以使其细节更加完善。
把某些逻辑用来标记工件(标记、文本、注释或占位符)的对象称为处理器,而一组这样的处理器(可能还有一些额外的工件)通常由方言组成(方言是指包含以th开头的属性,如)。Thymeleaf的核心库开箱即用地提供了一种称为标准方言的方言,对大多数用户来说这就足够了。
注意,方言实际上可以没有处理器,并且完全由其它类型的工件组成,但是处理器绝对是最常见的用例。
当然,如果想在利用库的高级特性的同时,定义自己的处理逻辑,那么,可以创建自己的方言(甚至扩展标准方言)。Thymeleaf还可以配置为一次使用几种方言。
标准方言的大多数处理器是属性处理器。这允许浏览器在处理HTML模板文件之前就正确地显示它们,因为它们会忽略额外的属性。例如,虽然使用标记库的JSP可能包含一些代码片段,但浏览器不能直接显示这些代码片段,比如:
用标准方言实现相同的功能。
这段代码不仅可以准确显示,而且还可以指定一个属性值(本例为James Carrot),当在浏览器中静态打开,这个属性值就能显示出来。而这将在处理模板时,由${user.name}的值替代。
直接使用了webjars。
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.webjars
webjars-locator
0.34
org.webjars
jquery
3.3.1
org.webjars
bootstrap
4.1.3
pom的完整内容在后面。
在resources/templates下,创建index.html。
thymeleaf模板页面默认放在/templates下。如无特殊说明,所有html都在这里。
主页
来自Thymeleaf模板的内容
Hello Thymeleaf~
Location: templates/index.html
不加任何内容的controller,访问index。
package com.thm.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
@RequestMapping("/index")
public String index() {
return "index";
}
}
也可不加,基本都是默认配置。
# 可改变模板文件的位置
#spring.thymeleaf.prefix=/WEB-INF/page/
spring.thymeleaf.encoding=UTF-8
# 开发时关闭缓存,不然没法看到实时页面
spring.thymeleaf.cache=false
package com;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ThymeApplication {
public static void main(String[] args) {
SpringApplication.run(ThymeApplication.class, args);
}
}
运行,访问http://localhost:8080/,看下效果。
在main里创建目录webapp/WEB-INF/page,创建文件index.html。
index
Thymeleaf首页
这是个例子
Location: webapp/WEB-INF/page/index.html
# 改变模板文件的位置
spring.thymeleaf.prefix=/WEB-INF/page/
运行,访问http://localhost:8080/index,对比变化的地方。
可见到访问的位置已经发生了变化。
多语言内容
个人信息
编号:3
姓名:这是姓名
性别:男
年龄:22
电话:15812341111
其中的显示的字段会被资源文件中的字符串替换掉。
多语言资源文件默认放在/static/下,可在这里建独立目录i18n,放以特定文件名开头的不同语言的文件。
1、中文,messages_zh_CN.properties,需要用unicode编码,通过native2ascii a.txt转换出来。
student.id=1
student.name=\u4f4f\u5bbf\u8d39
student.gender=\u5e74\u6ee1
student.age=882
student.phone=13111112222
2、英文,默认的,messages.properties,不需要转换
student.id=1
student.name=住宿费
student.gender=年满
student.age=882
student.phone=13111112222
3、修改application.properties,设置资源文件位置
spring.messages.basename=static/i18n/messages
#缓存刷新时间
spring.messages.cache-seconds=2
spring.messages.encoding=UTF-8
加上新的映射。
@RequestMapping("/sst")
public String showStudent() {
return "show";
}
运行,看看效果,http://localhost:8080/show。
访问数据库,用mongodb。数据库-test,用户名/密码-test/test,表名(集合)是userInfo。
@Document(collection = "userInfo")
public class User implements Serializable {
private static final long serialVersionUID = -1L;
@Id
private String id;
private long uid;
private String userName;
private String userAddr;
public User() {
super();
}
public User(Integer uid, String userName, String userAddr) {
super();
this.uid = uid;
this.userName = userName;
this.userAddr = userAddr;
}
public User(String id, Integer uid, String userName, String userAddr) {
super();
this.id = id;
this.uid = uid;
this.userName = userName;
this.userAddr = userAddr;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public long getUid() {
return uid;
}
public void setUid(long uid) {
this.uid = uid;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAddr() {
return userAddr;
}
public void setUserAddr(String userAddr) {
this.userAddr = userAddr;
}
@Override
public String toString() {
return "User [id=" + id + ", uid=" + uid + ", userName=" + userName + ", userAddr=" + userAddr + "]";
}
}
package com.thm.dao;
import java.util.List;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.thm.model.User;
public interface UserRepository extends MongoRepository {
User findByUserName(String userName);
List findByUserNameStartingWith(String prefix);
List findByUserNameEndingWith(String suffix);
void deleteByUid(long uid);
}
package com.thm.service;
import java.util.List;
import com.thm.model.User;
public interface UserService {
void save(User user);
void delByUid(long uid);
void delById(String id);
void update(User user);
User findByUserName(String userName);
List findByNameStartingWith(String prefix);
List findByNameEndingWith(String suffix);
List findList();
User findById(String id);
}
package com.thm.service;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.thm.dao.UserRepository;
import com.thm.model.User;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepo;
@Override
public void save(User user) {
userRepo.save(user);
}
@Override
public User findByUserName(String userName) {
return userRepo.findByUserName(userName);
}
@Override
public List findByNameStartingWith(String prefix) {
return userRepo.findByUserNameStartingWith(prefix);
}
@Override
public List findByNameEndingWith(String suffix) {
return userRepo.findByUserNameEndingWith(suffix);
}
@Override
public List findList() {
return userRepo.findAll();
}
@Override
public User findById(String id) {
Optional opUser = userRepo.findById(id);
return opUser.orElse(null);
}
@Override
public void update(User user) {
userRepo.save(user);
}
@Override
public void delByUid(long uid) {
userRepo.deleteByUid(uid);
}
@Override
public void delById(String id) {
userRepo.deleteById(id);
}
}
图省事,写一起了。这一层也可以去掉,直接用dao。
package com.thm.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.thm.model.User;
import com.thm.service.UserService;
@Controller
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserService userService;
private static final String RET_USER = "redirect:/user/";
@RequestMapping(method = RequestMethod.GET)
public String getUserList(ModelMap map) {
map.addAttribute("users", userService.findList());
return "userList";
}
// 显示创建用户的表单
@RequestMapping(value = "/create", method = RequestMethod.GET)
public String createUser(ModelMap map) {
map.addAttribute("user", new User());
map.addAttribute("action", "create");
return "userForm";
}
/**
* 创建用户
* 处理"/user"的POST请求,用来获取用户列表
* 通过@ModelAttribute绑定参数,也通过@RequestParam从页面中传递参数
*/
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String postUser(@ModelAttribute User user) {
userService.save(user);
return RET_USER;
}
/**
* 更新用户表单
* 处理"/user/{id}"的GET请求,通过URL中的id值获取User信息
*/
@RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
public String getUser(@PathVariable(name = "id") String id, ModelMap map) {
map.addAttribute("user", userService.findById(id));
map.addAttribute("action", "update");
return "userForm";
}
/**
* 处理"/user/{id}"的PUT请求,更新User
*/
@RequestMapping(value = "/update", method = RequestMethod.POST)
public String putUser(@ModelAttribute User user) {
userService.update(user);
return RET_USER;
}
/**
* 处理"/user/{uid}"的GET请求,删除User
*/
@RequestMapping(value = "/deletebyuid/{uid}", method = RequestMethod.GET)
public String deleteUser(@PathVariable(name = "uid") long uid) {
userService.delByUid(uid);
return RET_USER;
}
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
public String deleteUser(@PathVariable(name = "id") String id) {
userService.delById(id);
return RET_USER;
}
}
更新application.properties
# 数据库连接
spring.data.mongodb.uri=mongodb://test:test@localhost:27017/test
1,新增userform.html
userForm
2,列表userlist.html
userList
org.springframework.boot
spring-boot-starter-data-mongodb
运行,http://localhost:8080/user
4.0.0
com.sitech.billing.biop
webt
jar
1.0.0
Thymeleaf Exam
org.springframework.boot
spring-boot-starter-parent
2.0.4.RELEASE
UTF-8
UTF-8
1.8
2.0.0.RELEASE
Finchley.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
org.webjars
webjars-locator
0.34
org.webjars
jquery
3.3.1
org.webjars
bootstrap
4.1.3
org.springframework.boot
spring-boot-starter-data-mongodb
com.google.code.gson
gson
org.springframework.boot
spring-boot-devtools
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin