Spring Boot 推荐使用 Thymeleaf 作为其视图模板引擎。Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎,它与 JSP、Velocity、FreeMaker 等模板引擎类似,也可以轻易地与 Spring MVC 等 Web 框架集成。
Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为 “.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
本文将结合实例讲讲如何在 Spring Boot 项目里使用 Thymeleaf、JQuery、Bootstrap 等。
Spring Boot: https://spring.io/projects/spring-boot/
Thymeleaf:https://www.thymeleaf.org/
JQuery: https://jquery.com/
Bootstrap: https://getbootstrap.com/
1. 开发环境
Windows版本:Windows 10 Home (20H2)
IntelliJ IDEA (https://www.jetbrains.com/idea/download/):Community Edition for Windows 2020.1.4
Apache Maven (https://maven.apache.org/):3.8.1
注:Spring 开发环境的搭建,可以参考 “ Spring基础知识(1)- Spring简介、Spring体系结构和开发环境配置 ”。
2. 创建 Spring Boot 项目
1) 运行 IDEA 创建项目
点击菜单 New 创建 Project:
New Project -> Project Type: Maven -> Project SDK: 1.8 -> Check "Create from archtype" -> select "org.apache.maven.archtypes:maven-archtype-quickstart" -> Next
Name: SpringbootExample02
GroupId: com.example
ArtifactId: SpringbootExample02
-> Finish
2) 生成的项目目录结构
|-- src
| |-- main
| | |-- java
| | |-- com
| | |-- example
| | |-- App.java
| |-- test
| |-- java
| |-- com
| |-- example
| |-- AppTest.java
|-- pom.xml
3) Spring Boot Web 配置
参考 “ Springboot基础知识(08)- spring-boot-starter-web(Web启动器)” 的 “3. 配置 Spring Boot Web” 部分,完成 Spring Boot Web 配置。
(1) 配置后的 pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2
3 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>com.example</groupId>
8 <artifactId>SpringbootExample02</artifactId>
9 <version>1.0-SNAPSHOT</version>
10
11 <name>SpringbootExample02</name>
12 <!-- FIXME change it to the project's website -->
13 <url>http://www.example.com</url>
14
15 <properties>
16 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
17 <maven.compiler.source>1.8</maven.compiler.source>
18 <maven.compiler.target>1.8</maven.compiler.target>
19 </properties>
20
21 <packaging>jar</packaging>
22
23 <parent>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-parent</artifactId>
26 <version>2.6.6</version>
27 <relativePath/> <!-- lookup parent from repository -->
28 </parent>
29
30 <dependencies>
31 <dependency>
32 <groupId>junit</groupId>
33 <artifactId>junit</artifactId>
34 <version>4.11</version>
35 <scope>test</scope>
36 </dependency>
37 <dependency>
38 <groupId>org.springframework.boot</groupId>
39 <artifactId>spring-boot-starter-web</artifactId>
40 </dependency>
41 <!-- 打包 war 时,要把tomcat依赖注释掉 -->
42 <dependency>
43 <groupId>org.springframework.boot</groupId>
44 <artifactId>spring-boot-starter-tomcat</artifactId>
45 <scope>provided</scope>
46 </dependency>
47 <dependency>
48 <groupId>org.springframework.boot</groupId>
49 <artifactId>spring-boot-starter-test</artifactId>
50 <scope>test</scope>
51 </dependency>
52 </dependencies>
53
54 <build>
55 ...
56 </build>
57 </project>
在IDE中项目列表 -> SpringbootExample02 -> 点击鼠标右键 -> Maven -> Reload Project
(2) 修改 src/main/java/com/example/App.java 文件
1 package com.example;
2
3 import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5
6 @SpringBootApplication
7 public class App {
8 public static void main(String[] args) {
9 SpringApplication.run(App.class, args);
10 System.out.println("Spring boot example project");
11 }
12 }
(3) 创建 src/main/java/com/example/ServletInitializer.java 文件
1 package com.example;
2
3 import org.springframework.boot.builder.SpringApplicationBuilder;
4 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
5
6 public class ServletInitializer extends SpringBootServletInitializer {
7
8 @Override
9 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
10 return application.sources(App.class);
11 }
12
13 }
(4) 创建 src/main/java/com/example/controller/IndexController.java 文件
1 package com.example.controller;
2
3 import org.springframework.stereotype.Controller;
4 import org.springframework.web.bind.annotation.RequestMapping;
5 import org.springframework.web.bind.annotation.ResponseBody;
6
7 @Controller
8 public class IndexController {
9 @ResponseBody
10 @RequestMapping("/test")
11 public String test() {
12 return "Test Page";
13 }
14 }
(5) 创建 src/main/resources/application.properties 文件
1 spring.main.banner-mode=off
2
3 # Web server
4 server.display-name=SpringbootExample02-Test
5 server.address=localhost
6 server.port=9090
(6) 运行
Edit Configurations
Click "+" add new configuration -> Select "Maven"
Command line: clean spring-boot:run
Name: SpringbootExample02 [clean,spring-boot:run]
-> Apply / OK
Click Run "SpringbootExample02 [clean,spring-boot:run]"
...
Spring boot example project
访问 http://localhost:9090/test
Test Page
注:打包可以将 Command line 改成 clean package spring-boot:repackage
3. 导入 Thymeleaf 依赖包
访问 http://www.mvnrepository.com/,查询 Thymeleaf
修改 pom.xml:
1 <project ... >
2 ...
3 <dependencies>
4 ...
5
6 <!-- Thymeleaf -->
7 <dependency>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-starter-thymeleaf</artifactId>
10 </dependency>
11
12 ...
13 </dependencies>
14
15 ...
16 </project>
在IDE中项目列表 -> SpringbootExample02 -> 点击鼠标右键 -> Maven -> Reload Project
4. 配置静态资源(jQuery、Bootstrap、Images)
本文使用 jQuery 3.6.0 和 Bootstrap 4.2.1,两者放到 src/main/resources/static/lib/ 目录下,图片放在 src/main/resources/static/images/ 目录下。
目录结构如下
static
|- images
| |- bootstrap-solid.svg
|
|- lib
|- jquery
| |- jquery-3.6.0.min.js
|
|- bootstrap-4.2.1-dist
|- css
| |- bootstrap.min.css
| ...
|
|- js
|- bootstrap.min.js
...
注:bootstrap-solid.svg 的下载自 https://v4.bootcss.com/docs/4.6/assets/brand/bootstrap-solid.svg
5. 配置 Thymeleaf 模版
Thymeleaf 模板的默认位置在 resources/templates 目录下,默认的后缀是 html,即只要将 HTML 页面放在 “classpath:/templates/” 下,Thymeleaf 就能自动进行渲染。
1) 创建 src/main/resources/templates/common.html 文件
1 <div th:fragment="header(var)">
2 <meta charset="UTF-8">
3 <title th:text="${var}">Title</title>
4 <link rel="stylesheet" th:href="@{/lib/bootstrap-4.2.1-dist/css/bootstrap.min.css}" href="/lib/bootstrap-4.2.1-dist/css/bootstrap.min.css">
5 <script language="javascript" th:src="@{/lib/jquery/jquery-3.6.0.min.js}" src="/lib/jquery/jquery-3.6.0.min.js"></script>
6 <script language="javascript" th:src="@{/lib/bootstrap-4.2.1-dist/js/bootstrap.min.js}" src="/lib/bootstrap-4.2.1-dist/js/bootstrap.min.js"></script>
7 </div>
8
9 <div th:fragment="content-header" class="container" id="content-header-id">
10 <nav class="navbar navbar-light bg-light">
11 <a class="navbar-brand" href="#">
12 <img th:src="@{/images/bootstrap-solid.svg}" src="/images/bootstrap-solid.svg" width="30" height="30" class="d-inline-block align-top" alt="">
13 Thymeleaf Demo
14 </a>
15 </nav>
16 </div>
17
18 <div th:fragment="content-footer(var)" class="container" id="content-footer-id">
19 <p th:text="${var}">Content Footer</p>
20 </div>
2) 创建 src/main/resources/templates/home.html 文件
1 <!DOCTYPE html>
2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3 <head th:include="common::header(var='Home Page')">
4 </head>
5 <body>
6 <div th:replace="common::content-header"></div>
7
8 <div class="container" id="content" th:style="'min-height: 480px;'">
9 <p> </p>
10 <h3 th:text="'Welcome ' + ${name}">Welcome</h3>
11
12 <p> </p>
13 <p>Message: <span id="message"></span></p>
14 </div>
15
16 <div th:replace="common::content-footer(var='Copyright © 2020')"></div>
17
18 <script type="text/javascript">
19 $(document).ready(function(){
20 console.log("jQuery is running");
21
22 $("#message").html("jQuery is running");
23 });
24 </script>
25 </body>
26 </html>
3) 修改 src/main/java/com/example/controller/IndexController.java 文件
1 package com.example.controller;
2
3 import org.springframework.ui.Model;
4 import org.springframework.stereotype.Controller;
5 import org.springframework.web.bind.annotation.RequestMapping;
6 import org.springframework.web.bind.annotation.ResponseBody;
7
8 @Controller
9 public class IndexController {
10 @ResponseBody
11 @RequestMapping("/test")
12 public String test() {
13 return "Test Page";
14 }
15
16 @RequestMapping("/home")
17 public String home(Model model) {
18 model.addAttribute("name", "admin");
19 return "home";
20 }
21 }
访问 http://localhost:9090/home
[Logo] Thymeleaf Demo
Welcome admin
Message: jQuery is running
Copyright © 2020
6. 国际化
1) 编写国际化资源文件
在 src/main/resources 下创建一个 i18n 的目录,并在该目录中按照国际化资源文件命名格式分别创建以下三个文件:
home.properties:无语言设置时生效
home_en_US.properties:英语时生效
home_zh_CN.properties:中文时生效
以上国际化资源文件创建完成后,IDEA 会自动识别它们,并转换成 Resource Bundle 模式。
打开 home.properties,点击窗口底部 Resource Bundle 标签,然后点击 “+” 号,创建属性。
修改后的 home.properties 文件
home.title=Welcome(default)
home.message=Message(default)
home.status_on=jQuery is running(default)
home.status_off=jQuery is off (default)
修改后的 home_en_US.properties 文件
home.title=Welcome
home.message=Message
home.status_on=jQuery is running
home.status_off=jQuery is off
修改后的 home_zh_CN.properties 文件
home.title=欢迎
home.message=信息
home.status_on=jQuery 正在运行
home.status_off=jQuery 没有生效
2) 修改 src/main/resources/application.properties 文件,添加如下内容:
spring.messages.basename=i18n.home
spring.messages.encoding=UTF-8
3) 修改 src/main/resources/templates/home.html 文件
1 <!DOCTYPE html>
2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
3 <head th:include="common::header(var='Home Page')">
4 </head>
5 <body>
6 <div th:replace="common::content-header"></div>
7
8 <div class="container" id="content" th:style="'min-height: 480px;'">
9 <p> </p>
10 <h3 th:text="#{home.title} + ' ' + ${name}">Welcome</h3>
11
12 <p> </p>
13 <p><span th:text="#{home.message}">Message</span>:
14 <span id="message" th:text="#{home.status_off}"></span></p>
15 </div>
16
17 <div th:replace="common::content-footer(var='Copyright © 2020')"></div>
18
19 <script type="text/javascript" th:inline="javascript">
20 $(document).ready(function(){
21 console.log("jQuery is running");
22
23 $("#message").html([[#{home.status_on}]]);
24 });
25 </script>
26 </body>
27 </html>
访问 http://localhost:9090/home
注:Spring Boot 根据浏览器放出的请求头的 Accept-Language 来自动选择资源文件,比如 Accept-Language: zh-CN 映射到 home_zh_CN.properties,Accept-Language: en-US 映射到 home_en_US.properties,其它值会默认映射到 home.properties。
6. 使用 spring-boot-maven-plugin 插件运行打包
1) 修改 pom.xml
1 <project ... >
2 ...
3
4 <build>
5 <finalName>SpringbootExample02</finalName>
6 <plugins>
7 <plugin>
8 <groupId>org.springframework.boot</groupId>
9 <artifactId>spring-boot-maven-plugin</artifactId>
10 <configuration>
11 <mainClass>com.example.App</mainClass>
12 <layout>JAR</layout>
13 </configuration>
14 <executions>
15 <execution>
16 <goals>
17 <goal>repackage</goal>
18 </goals>
19 </execution>
20 </executions>
21 </plugin>
22 </plugins>
23 ...
24 </build>
25 </project>
layout 属性用来指定打成 jar 还是 war 文件,可用的值包括:ZIP 、JAR 、WAR、 NONE
在IDE中项目列表 -> SpringbootExample02 -> 点击鼠标右键 -> Maven -> Reload Project
2) 打包 jar
菜单 View -> Tool Windows -> Maven -> SpringbootExample02 -> Lifecycle -> Clean & Package
jar 包生成在目录 target/ 里
SpringbootExample02.jar
SpringbootExample02.jar.original
注:SpringbootExample02.jar 包含依赖包,可以直接运行。 SpringbootExample02.jar.original 里不包含依赖的包(要手动配置依赖环境),运行前要把文件名上的 “.original” 去掉。
点击 IDEA 底部 Terminal 标签页,执行如下命令。
$ java -jar target/SpringbootExample02.jar
...
Spring boot example project
访问 http://localhost:9090/test
Test Page
复制 src/main/resources/application.properties 文件到 target/ 目录下,修改 target/application.properties 配置如下:
spring.main.banner-mode=console
# Web server
server.display-name=SpringbootExample02-Test
server.address=localhost
server.port=8080
运行如下命令:
$ java -jar target/SpringbootExample02.jar --spring.config.location target/application.properties
...
Spring boot example project
访问 http://localhost:8080/test
Test Page
注:访问 http://localhost:9090/home 时,不能正常显示文字,因为需要国际化配置文件支持,这部分会在以后的外部配置文件实例中详细讲解。
3) 打包 war
把 pom.xml 里 <packaging>jar</packaging> 改成 <packaging>war</packaging>, spring-boot-maven-plugin 的 layout 属性改成 WAR,并把 spring-boot-starter-tomcat 依赖注释掉。
菜单 View -> Tool Windows -> Maven -> SpringbootExample02 -> Lifecycle -> Clean & Package
war 包生成在目录 target/ 里
SpringbootExample02.war
SpringbootExample02.war.original
把 SpringbootExample02.war 放到独立运行的 Tomcat 的 webapp 目录下,假设 Tomcat 运行在 8080 端口。
访问 http://localhost:8080/SpringbootExample02/test
Test Page
--------------------------------------
示例代码:https://gitee.com/slksm/public-codes/tree/master/demos/springboot-series/SpringbootExample02