- 前言
- 一、基础使用
- 二、环境配置
- 三、整合静态资源
- 四、访问路径支持
- 五、读取资源文件
- 六、内置对象
- 七、输出对象
- 八、页面逻辑
- 九、数据迭代
在经典的java单体项目中(前后端不分离),页面的编写往往采用JSP技术(Java Server Page),JSP的最大特点是可以在页面中编写java代码,实际上jsp经过转化生成Servlet,再编译生成*.class文件存储在WEB容器中,而对用户请求的处理正是由Servlet完成的。
使用JSP开发的主要问题是页面过于混乱,在HTML中编写JAVA代码往往只能由后台工程师完成,极大的提升了开发的难度,而页面的调试也需要先转换为Servlet再打包才能看到执行结果。SpringBoot项目默认使用内置的tomcat服务器,项目通常会被打成jar包放在jvm上直接执行(减少了部署WEB容器的环节),此时再采用JSP技术,就需要自建WEB-INF/web.xml文件,打成war包使用外部容器部署,这样的反而失去自身开发简洁的优势。
Thymeleaf是SpringBoot推荐使用的模板引擎,使用Thymeleaf可以按照HTML的方式编写代码,也同时可以实现JSP中的相关动态操作,而且不会生成*.class文件。
想要在项目中使用thymeleaf,首先需要导入spring-boot-starter-thymeleaf依赖包。
org.springframework.boot spring-boot-starter-thymeleaf 2.5.6
创建thymeleaf文件保存路径,使用thymeleaf语法编写的文件应该放在项目资源路径下。在src/mian下新建一个view文件夹并标记为资源根路径。
在src/mian/view下新建templates文件夹(必须叫这个名字),在templates文件夹中新建一个message子文件夹,在子文件夹内新建message_show.html页面。
编写message_show.html页面并引入thymeleaf命名空间。
Thymeleaf模板引擎
创建MessageAction处理类,接收message并传递到message_show.html页面显示。
@Controller
@RequestMapping("/message
@GetMapping("/page")
public String messagePage(Model model, String message) {
model.addAttribute("message", message);
return "message/message_show";
}
}
启动项目,访问:http://localhost:8080/message/page?message=hello Thymeleaf !!! 发现页面显示成功。
thymeleaf允许自定义配置,配置项写在application.yml文件中,例如修改保存的文件夹和页面后缀:
server:
port: 8080
spring:
thymeleaf:
prefix: classpath:/pages/
suffix: .page
实际上thymeleaf的所有配置属性保存在ThymeleafProperties类中,通过此类可以查看具体都存在哪些内容可以配置,配置的默认值是什么。
将view目录下的templates文件夹重命名为pages,将message_show.html文件重命名为message_show.page。
启动程序,访问:http://localhost:8080/message/page?message=hello,发现程序正常。
thymeleaf的全部配置项如下:
| No. | 属性 | 详情 |
|---|---|---|
| 1 | spring.thymeleaf.check-template | 在呈现模板之前检查模板是否存在 |
| 2 | spring.thymeleaf.check-template-location | 检查模板位置是否存在 |
| 3 | spring.thymeleaf.prefix | 在构建URL时预先查看名称的前缀 |
| 4 | spring.thymeleaf.suffix | 构建URL时附加到查看名称的后缀 |
| 5 | spring.thymeleaf.mode | 应用于模板的模板模式 |
| 6 | spring.thymeleaf.encoding | 模板编码 |
| 7 | spring.thymeleaf.cache | 启用模板缓存 |
| 8 | spring.thymeleaf.template-resolver-order | 链中模板解析器的顺序 |
| 9 | spring.thymeleaf.view-names | 可以解析的视图名称,逗号分隔 |
| 10 | spring.thymeleaf.excluded-view-names | 排除的视图名称 |
| 11 | spring.thymeleaf.enable-spring-el-compiler | 是否启用spring表达式编译 |
| 12 | spring.thymeleaf.enabled | 是否启用thymeleaf模板 |
| 13 | spring.thymeleaf.servlet.content-type | MIME类型 |
thymeleaf使用资源根路径下的static文件夹保存资源,包括css、js、图片、字体…
在view文件夹下新建static文件夹,在static文件夹下新建css、js、images文件夹,并编写一个index.html文件。在css文件夹下新建button-classic.css文件(下载button-classic.css)。
Thymeleaf静态资源
在js下新建index.js文件,编写一段javascript代码,点击按钮时放大图片。
window.onload = function() {
let changeBtn = document.getElementById('big-change-btn');
changeBtn.addEventListener('click',function() {
let imageDiv = document.getElementById('image-div');
imageDiv.style.width = imageDiv.offsetWidth + 100 + 'px';
})
}
目录结构如下:
重新启动项目,访问:http://localhost:8080/index.html可直接看到页面。
点击按钮,图片放大,html、图片、js、css都可以正常访问。
在thymeleaf模板页面中,可以使用@{}标记实现资源的路径定位。@{}标记是一个动态的符号,必须在动态页面中才能解析。
使用动态页面,那么请求应该由控制层跳转至显示层,新建PageAction:
@Controller
@RequestMapping("/message/*")
public class PageAction {
@GetMapping("/path")
public ModelAndView pathPage() {
ModelAndView mv = new ModelAndView("message/message_path"); // 跳转路径
return mv;
}
}
在view/templates/message文件夹下新建message-path.html文件,复制上例中index.html文件的内容,将资源路径用@{}包起来,在属性前加th:(所有动态的引用都需要加th:)。
完整的message-path.html文件:
Thymeleaf静态资源
启动项目,访问:http://localhost:8080/message/path可看到与上例相同的结果。
五、读取资源文件使用资源文件常常会伴随着国际化处理,在src/main/resource下新建一个i18n文件夹,在i18n中新建Message.properties文件。
com.template.title=Thymeleaf教程
com.template.content={0},好好学习哟!
新建中文版本资源文件Message_zh_CN.properties。
com.template.title=Thymeleaf教程
com.template.content={0},好好学习哟!
新建英文版本资源文件Message_en_US.properties。
com.template.title=Thymeleaf course
com.template.content={0}, study hard !
修改application.yml文件,配置资源的basename:
server:
port: 8080
spring:
messages:
basename: i18n/Message
在src/main/view/templates/message文件夹下新建message_i18n.html文件,项目结构如下:
thymeleaf页面中使用#{资源名称}的形式获取资源信息,示例:
如果资源存在占位符,使用#{资源名称(参数)}的形式传入,示例:
完整的message_i18n.html文件:
Thymeleaf静态资源
新建ThymeleafResourceAction用于页面跳转:
@Controller
@RequestMapping("/i18n/*")
public class ThymeleafResourceAction {
@GetMapping("/page")
public ModelAndView resourcePage() {
ModelAndView mv = new ModelAndView("message/message_i18n");
return mv;
}
}
启动项目,访问http://localhost:8080/i18n/page,资源加载成功。
以上代码虽然实现了资源文件的读取,但是依然存在着国际化的切换问题。可以通过一个参数lang配置区域,如果lang="zh_CN"展示中文资源,如果lang="en_US"展示英文资源。
新建ThymeleafConfig类,添加拦截器,将lang参数绑定到Locale上。
@Configuration
public class ThymeleafConfig implements WebMvcConfigurer {
@Bean(name="localeResolver") // locale解析器
public LocaleResolver getLocalResolver() { // 配置当前session对应的Locale
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); // 默认使用中文
return resolver;
}
public LocaleChangeInterceptor localeChangeInterceptor() { // Locale实例拦截器
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("lang"); // 绑定参数lang
return interceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) { // 添加拦截器
registry.addInterceptor(localeChangeInterceptor());
}
}
启动项目,不携带lang参数或输入http://localhost:8080/i18n/page?lang=zh_CN显示为中文,输入http://localhost:8080/i18n/page?lang=en_US切换为英文。
与jsp中的内置对象类似,thymeleaf中也提供了许多内置对象。
| No. | 内置对象 | 描述 |
|---|---|---|
| 1 | ${#ctx} | 上下文对象,可以获取其他内置对象 |
| 2 | ${#vars} | 获取上下文变量 |
| 3 | ${#locale} | 获取当前Locale设置 |
| 4 | ${#request} | HttpServletRequest对象实例 |
| 5 | ${#response} | HttpServletResponse对象实例 |
| 6 | ${#session} | HttpSession对象实例 |
| 7 | ${#servletContext} | ServletContext对象实例,或使用${#application} |
新建InnerObjectAction类,分别使用request、session、servletContext传递属性到页面。
@Controller
@RequestMapping("/message/*")
public class InnerObjectAction {
@GetMapping("/innerObject")
public String messagePage(HttpServletRequest request) {
request.setAttribute("message", "request范围传递");
request.getSession().setAttribute("message", "session范围传递");
request.getServletContext().setAttribute("message", "application范围传递");
return "message/message_inner_object";
}
}
在thymeleaf页面中可以使用${属性名}获取request范围的属性,使用${session.属性名}获取session范围的属性,使用${servletContext.属性名}或${application.属性名}获取application范围的属性。
也可以直接使用${内置对象.getAttribute(属性名)}获取传递到页面的属性。
在src/view/templates/message文件夹下新建message_inner_object.html页面:
Thymeleaf内置对象
启动项目,访问:http://localhost:8080/message/innerObject
thymeleaf页面可以直接输出java对象,常见的做法是在controller层携带java对象跳转到页面,在页面解析对象并展示。
新建一个Person类,此处使用lombok注解生成全参构造器:
@Data
@AllArgsConstructor
public class Person {
private Integer id;
private String name;
private Integer age;
private Double salary;
private Date birthday;
}
新建ShowObjectAction类,编写方法携带person对象跳转到object_show.html页面。
@Controller
@RequestMapping("/object/*")
public class ShowObjectAction {
@GetMapping("/person")
public String messagePage(Model model) {
Person person = new Person(1,"Annie",22,1234.56,new Date());
model.addAttribute("person", person);
return "message/object_show";
}
}
在src/main/view/templates/message下新建object_show.html页面。
Thymeleaf输出对象
启动项目,访问http://localhost:8080/object/person
除了使用${对象.属性}输出外,还可以通过内置对象进行数字、日期的格式化输出,例如:
输出一个对象的若干属性,可以采取简写形式,将对象写在父级元素上,在子元素中直接使用*{属性名}的方式输出。
Thymeleaf输出对象
八、页面逻辑
thymeleaf可以结合Spring表达式进行页面逻辑的控制。以上一节object_show.html页面为例。
判断是否成年:
是 未成年人 成年人
使用th:if标注的元素在条件成立时输出到页面,th:unless则相反。*{age lt 18}中的lt是Spring EL表达式中的符号,表示年龄小于18。
th:if中可以包含多个条件:
欢迎VIP用户,金额:
使用三元运算符输出:
由于groovy“非空即真”的特性,将三元运算符简化为了二元运算符。
您的id:
使用th:switch判断内容:
Tom Annie default
当所有条件都不满足时,使用th:case="*"进行默认处理。
完整的页面:
Thymeleaf输出对象
是
未成年人
成年人
欢迎VIP用户,金额:
您的身份是
您的id:
Tom
Annie
default
访问http://localhost:8080/object/person:
th:each可以在页面迭代输出集合数据。
以上代码为例,person是集合中的元数据,personStat包含了一些迭代的控制标志,使用:符号遍历集合,而${personList}则是控制层传递到页面的属性,该属性的类型是列表。
新建一个IterationAction类负责传递集合到页面:
@RestController
@RequestMapping("/iteration/*")
public class IterationAction {
@GetMapping("/list")
public ModelAndView list() {
ModelAndView mv = new ModelAndView("message/person_list");
List list = new ArrayList();
for (int x = 0; x < 10; x++) {
list.add(new Person(x + 1, "姓名-" + x, 10 + x, 300.32 * x, new Date()));
}
mv.addObject("personList", list);
return mv;
}
}
在src/main/view/templates/message下新建一个person_list.html页面,绘制表格,填充列表数据。
Thymeleaf迭代输出
No. 编号 姓名 年龄 工资 生日
启动项目,访问http://localhost:8080/iteration/list
在页面迭代输出Map集合则需要借助Entry,Entry中包含了key与value值。
在IterationAction类中新建map方法,携带map集合跳转到person_map.html页面。
@GetMapping("/map")
public ModelAndView map() {
ModelAndView mv = new ModelAndView("message/person_map");
Map map = new HashMap<>();
for (int x = 0; x < 10; x++) {
map.put(x, new Person(x + 1, "姓名-" + x, 10 + x, 300.32 * x, new Date()));
}
mv.addObject("personMap", map);
return mv;
}
在src/main/view/templates/message下新建一个person_map.html页面。
Thymeleaf迭代输出
No. key 编号 姓名 年龄 工资 生日
访问http://localhost:8080/iteration/map




