【Spring Boot】Spring Boot + Thymeleaf + Maven 使用示例

本页将介绍Spring Boot + Thymeleaf + Maven的例子。

我们将提供如何使用Spring BootThymeleaf来实现国际化(i18n)、表单验证和日志记录。

如果Spring Boot在类路径中扫描到Thymeleaf库,它将自动配置Thymeleaf

我们可以使用application.properties改变默认的Thymeleaf配置。

Thymeleaf是一个服务器端的模板引擎,可以处理XMLHTML等。

Thymeleaf可以从i18n消息文件中访问类字段和消息属性。

我们可以使用Thymeleaf将我们的类字段与HTML表单元素绑定。

我们可以使用Thymeleaf迭代我们的java集合。

在我们的例子中,我们将使用Thymeleaf执行表单验证和解除i18n消息。

如果Spring Boot启动器使用的是较低版本的Thymeleaf,我们还将提供如何使用Maven来使用Thymeleaf的高版本。

我们还将在Thymeleaf视图中使用CSS文件。

现在让我们一步一步地讨论这个完整的例子。

示例工具版本

  1. Java 8
  2. Spring Boot 1.5.3.RELEASE
  3. Thymeleaf 3.0
  4. Maven 3.3
  5. Eclipse Mars

在 Spring Boot 中集成 Thymeleaf 3

为了将ThymeleafSpring Boot集成,我们需要在构建工具(如MavenGradle)中使用以下Spring Boot启动器。

假设我们使用的是Maven,那么我们将使用以下Maven依赖项。

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

这都是关于在Spring Boot中配置Thymeleaf。当Spring Boot在类路径中找到Thymeleaf库时,Spring Boot会自动为Thymeleaf进行必要的配置。

在写这篇文章的时候,Thymeleaf 启动器的最新版本是1.5.3.RELEASE,它使用Thymeleaf 2.1版本。

如果我们想使用更高版本的Thymeleaf,例如Thymeleaf 3.0,那么我们需要在pom.xml中配置以下属性。
1. thymeleaf.version
2. thymeleaf-layout-dialect.version

假设我们使用的是Maven,那么上述属性将被配置为如下。

<properties>
   <thymeleaf.version>3.0.6.RELEASE</thymeleaf.version>
   <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
   <java.version>1.8</java.version>        
</properties> 

现在Spring Boot将使用Thymeleaf 3.0.6.RELEASE版本和Thymeleaf布局方言2.2.2版本和java 1.8版本。

使用 Thymeleaf

如果Spring Boot在其类路径中扫描到Thymeleaf库,那么我们就可以使用Thymeleaf了。

Spring BootThymeleaf提供了属性配置,这些属性将在application.propertiesapplication.yml中配置,以改变ThymeleafSpring Boot的配置。

我们在此列出其中的一些属性。

spring.thymeleaf.mode: 将应用于模板的模板模式。默认值是HTML 5

spring.thymeleaf.prefix: 这是将在视图名称前面加上的值,用于构建URL。默认值为classpath:/templates/
spring.thymeleaf.suffix: 这是将为视图名称添加后缀以生成URL的值。默认值为.html

在默认的Spring BootThymeleaf配置下,我们可以将Thymeleaf文件以html为扩展名放在以下位置。

src\main\resources\templates 

现在我们将讨论如何使用Thymeleaf创建表单元素。

使用 Thymeleaf 创建 < form >

假设我们在控制器类中有一个方法。

@Controller
@RequestMapping("app")
public class UserController {
  @GetMapping("create-user")
  public ModelAndView createUserView() {
    ModelAndView mav = new ModelAndView();
    mav.setViewName("user-creation");
    mav.addObject("user", new User());
    mav.addObject("allProfiles", getProfiles());
    return mav;
  }
  ---
} 

当我们访问/app/create-user时,名为user-creation.htmlThymeleaf文件将被打开,在那里我们将创建一个表单来创建用户。现在看看下面的代码片段。

mav.addObject("user", new User()); 

属性名称user将在<form>中与Thymeleafth:object属性一起使用。

<form action="#" th:action="@{/app/create-user}" th:object="${user}" method="POST"> 

th:action被指定为行动URL,将在表单提交时被调用。

在表单提交时,/app/create-user将访问控制器类中的以下方法。

@Controller
@RequestMapping("app")
public class UserController {
  ---
  @PostMapping("create-user")
  public ModelAndView createUser(@Valid User user, BindingResult result) {
    ---
  }
} 

现在我们将创建一些表单元素。假设我们有一个类,它有对应于表单元素的字段。

public class User { 
   private String userId;
   private String userName;
   private String gender;
   private Boolean married;
   private String profile;
} 

与表单元素如<input><select>的数据绑定是通过Thymeleafth:field属性实现的。

假设我们想创建一个输入文本框来获取用户ID

用户类的字段userId将使用Thymeleafth:field绑定到输入文本框,如下所示。

<input type="text" th:field="*{userId}" /> 

以同样的方式,其他表单元素将与用户类字段绑定。找到用户类的userName字段的输入框。

<input type="text" th:field="*{userName}" /> 

找到用户类的gender字段的单选按钮。

<input type="radio" th:field="*{gender}" value="Male"/>
<input type="radio" th:field="*{gender}" value="Female"/> 

找到用户类的married字段的复选框。

<input type="checkbox" th:field="*{married}" /> 

找到用户类的profile字段的选择元素。

<select th:field="*{profile}">
         <option th:each="profile : ${allProfiles}" th:value="${profile}" th:text="${profile}">Profile</option>
</select> 

Thymeleafth:each将遍历该集合。Thymeleafth:value属性赋值。

allProfiles是属性名称,将被添加到ModelAndView的每个请求中。

mav.addObject("allProfiles", getProfiles()); 

getProfiles()方法将返回所有profile的列表。

private List<String> getProfiles() {
   List<String> list = new ArrayList<>();
   list.add("Developer");
   list.add("Manager");
   list.add("Director");
   return list;
} 

Thymeleaf提供了th:text="${...}"的语法,可以用来访问java对象中的一个值。

如果我们想显示一个表格中所有项的值,我们写的代码如下。

<table>
 <tr th:each="user : ${allUsers}">
    <td th:text="${user.userId}">Id</td>
    <td th:text="${user.userName}">Title</td>
 </tr>	
</table> 

Thymeleaf中,我们可以使用th:href="@{..}"的语法来加载CSS或创建一个链接来重定向一个URL

国际化(i18n)

当我们使用Spring Boot启动器时,我们的Spring Boot应用程序就可以使用国际化(i18n)。

我们需要在以下位置创建属性文件。

src\main\resources\messages.properties
src\main\resources\messages_en.properties 

如果localeen,那么Spring应用程序将选择 messages_en.properties文件。

默认的i18n文件将是 messages.properties

我们可以使用application.properties文件中的spring属性改变默认的spring消息配置。例如:

spring.messages.basename:它为消息文件配置了逗号分隔的基础名称。默认是messages。

spring.messages.encoding: 它配置了消息包的编码。默认是UTF-8。

为了显示i18n信息,我们需要使用Thymeleafth:text="#{...}"语法。假设我们想为我们的页面标题显示i18n信息,为此我们在信息属性文件中定义了一个key,如下所示。

app.title= Spring Boot + Thymeleaf 

然后它将被Thymeleaf以如下方式显示。

<title th:text="#{app.title}"> Title </title> 

Thymeleaf提供了#locale上下文,使用该上下文我们可以显示特定地区的细节,如语言、国家,如下所示。

<p th:text="${#locale.language}"> language</p>
<p th:text="${#locale.country}"> country</p> 

验证 | Validation

为了验证一个字段,我们可以使用Hibernate验证器。当我们使用Spring Boot启动器时,Hibernate验证器库被自动配置在类路径中。

现在我们将在我们的类中使用验证器注解,以绑定表单。

验证器注解包括@NotNull@Size等,来自javax.validation库。

public class User { 
   @NotNull
   @Size(min=3, max=10)	
   private String userId;
   @NotNull
   @Size(min=5, max=20)	   
   private String userName;
   @NotNull   
   private String gender;
   private Boolean married;
   private String profile;
} 

要启用表单验证,我们需要在Spring控制器方法参数中使用javax.validation库中的@Valid注释,该参数将在表单提交时调用。

我们还需要SpringBindingResult的实例来知道表单是否经过验证。

@PostMapping("create-user")
public ModelAndView createUser(@Valid User user, BindingResult result) {
    ModelAndView mav = new ModelAndView();
    if(result.hasErrors()) {
       	logger.info("Validation errors while submitting form.");
       	mav.setViewName("user-creation");
        mav.addObject("user", user);
        mav.addObject("allProfiles", getProfiles());
        return mav;
    }		
    userService.addUser(user);
    mav.addObject("allUsers", userService.getAllUserArticles());
    mav.setViewName("user-info");
    logger.info("Form submitted successfully.");	    
    return mav;
} 

如果表单有验证错误,那么result.hasErrors()将返回true。如果表单中存在验证错误,那么我们应该再次调用同一个Thymeleaf视图,如果没有验证错误,则执行业务逻辑并重定向到成功视图。

现在在Thymeleaf视图中,我们需要显示验证错误信息。为了检查一个给定的字段名是否存在验证错误,Thymeleaf提供了#fields.hasErrors(...),它返回布尔值。

<label th:if="${#fields.hasErrors('userId')}" th:errors="*{userId}" th:class="'error'">Id Error</label> 

th:errors将在Hibernate验证器注解的基础上显示Spring的默认验证错误信息,我们已经在与表单元素绑定的类域中使用了该注解。

如果我们想对验证错误使用i18n消息,那么使用th:text="#{...}"

<label th:if="${#fields.hasErrors('userId')}" th:text="#{error.user.id}" th:class="'error'">Id Error</label> 

error.user.id是在messages_en.properties文件中定义的i18n属性。

日志 | Logging

Spring Boot应用程序中,Logback依赖性是自动解决的。

每个Spring Boot启动器都会自行添加spring-boot-starter-logging

要改变日志的默认配置,我们需要在application.properties文件中配置日志属性。

找到其中的一些属性。

logging.level.*: 它作为包名的前缀,用于设置日志级别。

logging.file: 它配置了一个日志文件名来记录日志的信息。

logging.path: 它只配置了日志文件的路径。Spring boot创建了一个名为spring.log的日志文件。

假设我们的类包是com.concretepage,那么可以在application.properties文件中使用logging.level.*来定义日志级别,如下所示。

logging.level.com.concretepage= INFO 

现在,在com.concretepage包或其子包下的任何类中,都将应用INFO级别的日志。我们可以使用org.slf4j.Logger,如下所示。

1. 在类级别实例化org.slf4j.Logger

private static final Logger logger = LoggerFactory.getLogger(UserController.class);

2. 现在,根据需要在类的任何地方使用logger

logger.info("Validation errors while submitting form."); 

完整示例

查找Spring bootThymeleaf的完整示例。

我们将创建具有国际化(i18n)、表单验证和日志的应用程序。

找到完整的代码。

1. 在 Eclipse 中项目结构

使用eclipse找到演示项目的结构。
在这里插入图片描述

2. Maven 文件

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>
	<groupId>com.concretepage</groupId>
	<artifactId>spring-boot-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	<name>spring-demo</name>
	<description>Spring Boot Demo Project</description>
	<parent>
	   <groupId>org.springframework.boot</groupId>
	   <artifactId>spring-boot-starter-parent</artifactId>
	   <version>1.5.3.RELEASE</version>
	</parent>
	<properties>
	   <thymeleaf.version>3.0.6.RELEASE</thymeleaf.version>
           <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
	   <java.version>1.8</java.version>        
	</properties>
	<dependencies>
	    <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	    </dependency>
	    <dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-thymeleaf</artifactId>
	    </dependency>	  
    	    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <optional>true</optional>
            </dependency> 
	</dependencies> 
	<build>
	    <plugins>
		<plugin>
		   <groupId>org.springframework.boot</groupId>
		   <artifactId>spring-boot-maven-plugin</artifactId>
		</plugin>
	     </plugins>
	</build>
</project> 

找到我们的例子中使用的Spring Boot启动器描述。

spring-boot-starter-parent: 依赖性管理的父级POM

spring-boot-starter-web: 构建WebREST应用程序的启动器。它使用Tomcat服务器作为默认的嵌入式服务器。

spring-boot-starter-thymeleaf : 用于ThymeleafSpring框架的集成。

spring-boot-devtools : 它提供了开发者工具。这些工具在应用开发模式中很有帮助。开发者工具的一个特点是在代码发生任何变化时自动重新启动服务器。

3. 创建 Domain 和 Service

User.java


package com.concretepage.domain;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class User { 
   @NotNull
   @Size(min=3, max=10)	
   private String userId;
   @NotNull
   @Size(min=5, max=20)	   
   private String userName;
   @NotNull   
   private String gender;
   private Boolean married;
   private String profile;
   public String getUserId() {
	return userId;
   }
   public void setUserId(String userId) {
	this.userId = userId;
   }
   public String getUserName() {
	return userName;
   }
   public void setUserName(String userName) {
	this.userName = userName;
   }
   public String getGender() {
	return gender;
   }
   public void setGender(String gender) {
	this.gender = gender;
   }
   public Boolean getMarried() {
	return married;
   }
   public void setMarried(Boolean married) {
	this.married = married;
   }
   public String getProfile() {
	return profile;
   }
   public void setProfile(String profile) {
	this.profile = profile;
   }  
}  

我们在上述类中使用Hibernate验证器进行表单验证。现在找到服务类。

UserService.java

package com.concretepage.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.concretepage.domain.User;
@Service
public class UserService {
	private List<User> allUsers = new ArrayList<>();
	public List<User> getAllUserArticles(){
		return allUsers;
	}
	public void addUser(User user) {
		allUsers.add(user);
	}
} 

4. 创建 Controller

UserController.java

package com.concretepage.controller;
import java.util.ArrayList;
import java.util.List;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.concretepage.domain.User;
import com.concretepage.service.UserService;
@Controller
@RequestMapping("app")
public class UserController {
	private static final Logger logger = LoggerFactory.getLogger(UserController.class);	
	@Autowired
	private UserService userService;
	@GetMapping("create-user")
	public ModelAndView createUserView() {
	    ModelAndView mav = new ModelAndView();
	    mav.setViewName("user-creation");
	    mav.addObject("user", new User());
	    mav.addObject("allProfiles", getProfiles());
	    return mav;
        }
	@PostMapping("create-user")
	public ModelAndView createUser(@Valid User user, BindingResult result) {
	    ModelAndView mav = new ModelAndView();
            if(result.hasErrors()) {
        	logger.info("Validation errors while submitting form.");
        	mav.setViewName("user-creation");
    	        mav.addObject("user", user);
    	        mav.addObject("allProfiles", getProfiles());
    	        return mav;
            }		
	    userService.addUser(user);
	    mav.addObject("allUsers", userService.getAllUserArticles());
	    mav.setViewName("user-info");
    	    logger.info("Form submitted successfully.");	    
	    return mav;
        }	
	private List<String> getProfiles() {
	    List<String> list = new ArrayList<>();
	    list.add("Developer");
	    list.add("Manager");
	    list.add("Director");
	    return list;
	}
} 

5. 创建 application.properties

application.properties

logging.level.root= WARN
logging.level.org.springframework.web= ERROR
logging.level.com.concretepage= INFO 

6. 创建用于国际化的 Message Properties

找到en语言的信息属性。

messages_en.properties

app.title= Spring Boot + Thymeleaf
app.create-user= Create User
app.user-details= User Details

user.id= Id
user.name= Name
user.gender= Gender
user.married= Married
user.profile= Profile

user.gender.male= Male
user.gender.female= Female

user.form.submit= Submit 
user.form.reset= Reset  
user.add-more-users= Add More Users 

error.user.id= Id must be between 3 to 10 characters.
error.user.name= User name must be between 5 to 20 characters.
error.user.gender= Select  gender. 

7. 创建 Thymeleaf 模板

当我们访问该应用程序时,将打开以下页面。

user-creation.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
    <head>
        <title th:text="#{app.title}"> Title </title>
        <link rel="stylesheet" th:href="@{/css/styles.css}"/>
    </head>
	<body>
	    <h1 th:text="#{app.create-user}">Create</h1>
	    <form action="#" th:action="@{/app/create-user}" th:object="${user}" method="POST">
	      <table>
	    	<tr><td th:text="#{user.id}"/></td>
	    	    <td>
	    	       <input type="text" th:field="*{userId}" />
	    	       <label th:if="${#fields.hasErrors('userId')}" th:text="#{error.user.id}" th:class="'error'">Id Error</label>
	    	    </td>
	    	</tr>
	    	<tr><td th:text="#{user.name}"></td>
	    	    <td>
	    	      <input type="text" th:field="*{userName}" />
	    	      <label th:if="${#fields.hasErrors('userName')}" th:text="#{error.user.name}" th:class="'error'">Name Error</label>
	    	    </td>
	    	</tr>
	    	<tr><td th:text="#{user.gender}"></td>
	    	   <td>
	    	       <input type="radio" th:field="*{gender}" value="Male"/><label th:text="#{user.gender.male}">M</label>
	    	       <input type="radio" th:field="*{gender}" value="Female"/><label th:text="#{user.gender.female}">F</label>
	    	       <label th:if="${#fields.hasErrors('gender')}" th:text="#{error.user.gender}" th:class="'error'">Gender Error</label>
	    	   </td>
	    	</tr>
	    	<tr><td th:text="#{user.married}+ '?'"></td>
	    	   <td>
	    	       <input type="checkbox" th:field="*{married}" />
	    	   </td>
	    	</tr>	    	
	    	<tr><td th:text="#{user.profile}"></td>
	    	   <td>
	    	       <select th:field="*{profile}">
	    	          <option th:each="profile : ${allProfiles}" th:value="${profile}" th:text="${profile}">Profile</option>
	    	       </select>
	    	   </td>
	    	</tr>	    		    	
	        <tr><td colspan="2">
	              <input type="submit" th:value="#{user.form.submit}"/> 
	              <input type="reset" th:value="#{user.form.reset}"/>
	            </td>
	        </tr>
	      </table>  
	    </form>
	</body>
</html> 

成功提交表格后,将打开以下页面。

user-info.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
      <title th:text="#{app.title}"> Title </title>
      <link rel="stylesheet" th:href="@{/css/styles.css}"/>
</head>
<body>
   <h1 th:text="#{app.user-details}">Details</h1>
    <table>
        <tr>
           <th th:text="#{user.id}"/></th>
           <th th:text="#{user.name}"></th>
           <th th:text="#{user.gender}"></th>
           <th th:text="#{user.married}+ '?'"></th>
           <th th:text="#{user.profile}"></th>
        </tr>
        <tr th:each="user : ${allUsers}">
	      <td th:text="${user.userId}">Id</td>
		  <td th:text="${user.userName}">Title</td>
		  <td th:text="${user.gender}">Gender</td>
		  <td th:text="${user.married}">Married</td>
		  <td th:text="${user.profile}">Profile</td>		  		  
	    </tr>	
	</table>
	<a href="#" th:href="@{/app/create-user}" th:text="#{user.add-more-users}">Add User</a>
</body>
</html> 

8. 创建CSS文件

styles.css

.error{
    color: red;
    font-size: 15px;
}
.user{
    color: blue;
    font-size: 15px;
}
table {
    border-collapse: collapse;
}

table, th, td {
    border: 1px solid black;
} 

9. Spring Boot 主类

找到Spring boot的主类来运行应用程序。

MyApplication.java

package com.concretepage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {  
    public static void main(String[] args) {
	SpringApplication.run(MyApplication.class, args);
    }       
} 

运行应用程序

我们可以通过以下方式运行我们的应用程序。

1. 使用Eclipse

使用页面末尾的下载链接下载项目的源代码。

将该项目导入eclipse

使用命令提示符,进入项目的根文件夹并运行。

mvn clean eclipse:eclipse 

然后在eclipse中刷新该项目。点击Run as -> Java Application来运行主类MyApplication

Tomcat服务器将被启动。

2. 使用Maven命令

下载项目的源代码。使用命令提示符进入项目的根文件夹并运行命令。

mvn spring-boot:run 

Tomcat服务器将被启动。

3. 使用可执行的JAR

使用命令提示符,转到项目的根文件夹并运行该命令。

mvn clean package 

我们将在目标文件夹中得到可执行的spring-boot-demo-0.0.1-SNAPSHOT.jar。以下列方式运行这个JAR

java -jar target/spring-boot-demo-0.0.1-SNAPSHOT.jar 

Tomcat服务器将被启动。

现在我们准备测试该应用程序。访问下面给出的URL。

http://localhost:8080/app/create-user 

我们将得到以下界面来创建用户。
在这里插入图片描述
成功提交表格后,我们将得到用户的报告页面。

在这里插入图片描述

参考文献

【1】Spring Boot Reference Guide
【2】Using Thymeleaf
【3】Spring Boot + Thymeleaf + Maven Example

源码下载

spring-boot-thymeleaf-maven-example.zip

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫巳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值