SpringBoot系列教程15--Web开发01之Thymeleaf使用

作者:一一哥

本章节我将带领大家学习Spring boot中实现Web开发.

一. Web开发方式简介

Spring boot提供了一套完整的web开发流程,从前端到后台,再到数据库,定时任务,消息队列等都可以支持.一般利用Spring框架开发一个Web应用有两种方式:

1. 前后端分离

这种方式前端开发和后端开发完全分离,只需要协商好接口就行,前端负责开发页面并调用后端接口展示数据,后端负责提供Restful风格的接口.

2. 使用Spring boot自带的模板

Springboot支持多种主流后端模板:
· Thymeleaf
· FreeMarker
· Groovy
· Mustache
· Velocity
· JSP

需要注意的是,虽然Spring MVC支持JSP,但是Spring Boot不建议使用JSP,因为在使用嵌入式servlet容器时,有一些使用限制.另外在2010年后Velocity停止更新,所以这两种都不建议使用.

以上几个模板Springboot可以同时支持.什么叫同时支持呢?简而言之,Springboot项目中可以同时共存多个模板,我们需要做的仅仅是在pom文件中引入相关模板引擎的jar包就可以了.Springboot可以根据模板的后缀名来决定到底由哪种模板引擎解析这个动态页面.

2.1 常见模板页面后缀

Thymeleaf : .html
freemaker : .ftl
jsp : jsp

2.2 前后端模板区别

注意以上这些模板都是后端模板,有别于前端模板(如angular).

1️⃣. 前端模板:

前端模板通常是通过模板提供的js,根据模板规定的语法规则解析html中的模板标记;

2️⃣. 后端模板:

类似于前端,一个页面请求到达之后,后端模板引擎根据特定的语法规则解析模板中的内容,将数据填充到模板中,最终返回给浏览器的实际上已经是一个完整的html页面了.

二. 用Spring Boot搭建Web项目

1. 创建Maven工程及其module

注意:

为了方便我们以后讲述其他SpringBoot知识点,我们建立一个SpringBoot项目,然后在这个项目中创建多个module,每个module讲述一个SpringBoot的知识点,这样我们就不用建立多个intelliJ项目了.

我们创建一个maven工程(注意,不要勾选create from archytype,虽然它会帮你创建项目骨架,但是会从外网下载一些东西,很慢,导致会卡在那)来创建Web项目.

1.1 创建一个父项目--boot-demos

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring

项目选择Maven构建

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_html_02

设置项目的GAV坐标

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_03

1.2 在父项目中创建一个子module--demo05

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_04

子module也是Maven架构.

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_Web_05

如果我们项目案例中用不到默认的src目录,可以把它删除了.

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_06

接下来我们就在demo05这个module中讲述如何进行实现一个简单的Web功能.

2.改造pom.xml文件

我们在demo05的pom.xml文件中,对代码进行改造,把项目改造成spring-boot项目,并且添加web依赖。

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

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

三. Thymeleaf简介

Thymeleaf是一个XML/XHTML/HTML5模板引擎,可用于Web与非Web环境中的应用开发.它提供了一个用于整合SpringMVC的可选模块,在应用开发中,你可以使用Thymeleaf来完全代替JSP或其他模板引擎,如Velocity\FreeMarker等.

1.Thymeleaf示例模板

<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</td>
<th th:text="#{msgs.headers.price}">Price</td>
</tr>
</thead>
<tbody>
<tr th:each="prod : ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price,1,2)}">0.99</td>
</tr>
</tbody>
</table>

可以看到Thymeleaf主要以属性的方式加入到html标签中,浏览器在解析html时,当检查到没有的属性时候会忽略掉该属性,所以Thymeleaf的模板可以通过浏览器直接打开展现,这样非常有利于前后端的分离.

2. 利用Thymeleaf模板实现Web开发步骤

2.1 添加thymeleaf依赖包

在我们的Spring Boot项目demo05中使用Thymeleaf,只需要引入下面依赖。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

2.2 创建thymeleaf模板文件

在​​src/main/resources/​​​目录下创建一个文件夹​​templates​​,默认情况下名称固定,在该目录下创建一个index.html.

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_07

<!DOCTYPE html>
<html lang="en">
<head>
<!--注意:这个meta节点最后有个结束的'/',一定要注意,否则会产生异常!!!后续我们再分析如何解决这个异常-->
<meta charset="UTF-8"/>
<title>index</title>
</head>
<body>
<!--${msg},thymeleaf模板根据key取值-->
<h1 th:text="${msg}">Hello</h1>
</body>
</html>

2.3 编写controller代码

创建一个HelloController类,里面编写一个controller接口,如图所示.

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_Web_08

@Controller
public class HelloController {

@RequestMapping("/")
public String index(ModelMap map) {
// 添加一个属性,用来在模板中根据这个key来读取对应的值
map.addAttribute("msg", "跟一一哥学习SpringBoot");
// return 模板文件的名称-->对应src/main/resources/templates/index.html
return "index";
}
}

2.4 创建Application入口类

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_Web_09

package com.yyg.boot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
* 创建web项目
*/
@SpringBootApplication
public class WebApplication {

public static void main(String[] args){
SpringApplication.run(WebApplication.class,args);
}

}

完整的项目结构:

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_html_10

完整的pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>
<artifactId>demo05</artifactId>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<dependencies>
<!--web依赖包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--thymeleaf的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!--为了解决thymeleaf模板中,对html标签要求太严格的问题!-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

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

</project>

2.5 启动入口类

在浏览器中输入​​http://localhost:8080/,看到如下结果​​.

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_11

这就是利用Thymeleaf模板来渲染的一个页面,
做到了不破坏HTML自身内容的数据逻辑分离.

更多Thymeleaf的页面语法,可以参考我的另一篇关于Thymeleaf的博客!

四. SAXParseException异常处理方案

1. 问题描述

如果我们的模板文件,也就是index.html文件,在编写的时候是默认生成的html文件,如图所示:

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_spring_12

那么在启动项目后,访问接口,可能会产生如下异常:

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_html_13

org.xml.sax.SAXParseException: 元素类型 "meta" 必须由匹配的结束标记 "</meta>" 终止。

2. 产生该异常的原因如图示

SpringBoot2.x系列教程15--Web开发01之Thymeleaf使用_Web_14

3. 解决方案

1️⃣.修改​​thymeleaf.mode​​​的值为LEGACYHTML5;
2️⃣.在pom.xml文件中添加一个依赖包:

<!--为了解决thymeleaf模板中,对html标签要求太严格的问题!-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>

做完以上两步之后,以后的html文件中,即使标签不是成对出现或者标签没有结束标签,也不会再解析异常了.

五. Spring Boot中的配置文件

在SpringBoot中,如有需要修改默认配置的时候,只需复制下面要修改的属性到application.properties中,并修改成需要的值,如修改模板文件的扩展名,修改默认的模板路径等.

1. Thymeleaf默认的配置属性

# Enable template caching.
spring.thymeleaf.cache=true

# Check that the templates location exists.
spring.thymeleaf.check-template-location=true

# Content-Type value.
spring.thymeleaf.servlet.content-type=text/html

# Enable MVC Thymeleaf view resolution.
spring.thymeleaf.enabled=true

# Template encoding.
spring.thymeleaf.encoding=UTF-8

# Comma-separated list of view names that should be excluded from resolution.
spring.thymeleaf.excluded-view-names=

# Template mode to be applied to templates. See also StandardTemplateModeHandlers.
spring.thymeleaf.mode=HTML5

# Prefix that gets prepended to view names when building a URL.
spring.thymeleaf.prefix=classpath:/templates/

# Suffix that gets appended to view names when building a URL.
spring.thymeleaf.suffix=.html

# Order of the template resolver in the chain.
spring.thymeleaf.template-resolver-order=

# Comma-separated list of view names that can be resolved.
spring.thymeleaf.view-names=