Spring Boot Flash 属性教程展示了如何在 Spring Boot 应用中创建 Flash 消息。
Spring 是流行的 Java 应用框架,而 Spring Boot 是 Spring 的演进,可以帮助轻松地创建独立的,生产级的基于 Spring 的应用。
Flash 消息是用于用户通知或存储表单输入的临时数据。 它们存储在一个会话中,并且一旦检索就消失。
使用RedirectAttributes's
addFlashAttribute()
在 Spring 中将 Flash 消息创建为 Flash 属性。 它们与RedirectView
结合使用。
Spring Boot Flash 属性示例
在以下应用中,我们创建用于通知和记住表单输入值的 Flash 属性。 我们有一个带有两个输入的表格。 如果输入值不符合验证标准,则应用将重定向到表单页面并显示错误消息; 这些消息作为 Flash 属性发送。
此外,还可以记住表单的正确值。
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ └───controller
│ │ MyController.java
│ │
│ └───resources
│ └───templates
│ index.html
│ showMessage.html
└───test
└───java
这是 Spring 应用的项目结构。
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.zetcode</groupId>
<artifactId>springflashmessage</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这是 Maven pom.xml
文件。 我们使用spring-boot-starter-thymeleaf
与 Thymeleaf 进行模板化,并使用hibernate-validator
进行表单数据验证。
com/zetcode/controller/MyController.java
package com.zetcode.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;
import org.thymeleaf.util.StringUtils;
import javax.validation.ConstraintViolationException;
import javax.validation.constraints.Size;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
@Controller
@Validated
public class MyController {
@RequestMapping("/")
public String index(Model model) {
return "index";
}
@RequestMapping("/message")
public ModelAndView message(@RequestParam @Size(min = 2, max = 255) String name,
@RequestParam @Size(min = 2, max = 255) String occupation) {
var msg = String.format("%s is a %s", name, occupation);
Map<String, Object> params = new HashMap<>();
params.put("message", msg);
return new ModelAndView("showMessage", params);
}
@ExceptionHandler(ConstraintViolationException.class)
public RedirectView handleError(ConstraintViolationException ex,
WebRequest request,
RedirectAttributes atts) {
var name = request.getParameter("name");
var occupation = request.getParameter("occupation");
var errorMessages = new ArrayList<String>();
var violations = ex.getConstraintViolations();
violations.forEach(violation -> {
var error = String.format("%s: %s", violation.getPropertyPath(),
violation.getMessage());
errorMessages.add(error);
});
if (!StringUtils.isEmptyOrWhitespace(name)) {
atts.addFlashAttribute("name", name);
}
if (!StringUtils.isEmptyOrWhitespace(occupation)) {
atts.addFlashAttribute("occupation", occupation);
}
atts.addFlashAttribute("messages", errorMessages);
var redirectView = new RedirectView("/");
return redirectView;
}
}
这是MyController
。 它响应来自客户端的请求。 它找出当前日期和时间,并将处理过程解析为showMessage.ftl
模板,并将其传递给数据。
@Controller
@Validated
public class MyController {
@Validated
注解验证带注解的请求参数。 在我们的例子中,我们使用两个@Size
注解。
@RequestMapping("/")
public String index(Model model) {
return "index";
}
根页面返回索引视图,该视图将表单发送给客户端。
@RequestMapping("/message")
public ModelAndView message(@RequestParam @Size(min = 2, max = 255) String name,
@RequestParam @Size(min = 2, max = 255) String occupation) {
var msg = String.format("%s is a %s", name, occupation);
Map<String, Object> params = new HashMap<>();
params.put("message", msg);
return new ModelAndView("showMessage", params);
}
此操作响应表单提交。 两个输入参数,名称和职业用@Size
注解。 如果一切正常,将根据参数构建一条消息,并使用showMessage
视图将其发送到客户端。
@ExceptionHandler(ConstraintViolationException.class)
public RedirectView handleError(ConstraintViolationException ex,
WebRequest request,
RedirectAttributes atts) {
如果输入参数未能通过验证,则会抛出ConstraintViolationException
。 我们在提供的异常处理程序中对异常做出反应。
var name = request.getParameter("name");
var occupation = request.getParameter("occupation");
我们得到了请求参数。 它们用于保留正确的表单输入值。
var errorMessages = new ArrayList<String>();
var violations = ex.getConstraintViolations();
violations.forEach(violation -> {
var error = String.format("%s: %s", violation.getPropertyPath(),
violation.getMessage());
errorMessages.add(error);
});
我们得到约束违例并建立错误消息列表。 错误消息将显示在表单上方的索引表单页面中。
if (!StringUtils.isEmptyOrWhitespace(name)) {
atts.addFlashAttribute("name", name);
}
if (!StringUtils.isEmptyOrWhitespace(occupation)) {
atts.addFlashAttribute("occupation", occupation);
}
如果填充的输入参数不为空并且不仅包含空格,则将它们与addFlashAttribute()
一起存储为 Flash 属性。
atts.addFlashAttribute("messages", errorMessages);
错误消息存储为 flash 属性。
var redirectView = new RedirectView("/");
return redirectView;
我们使用RedirectView
重定向到表单页面。
templates/index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home page</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.css"
rel="stylesheet">
</head>
<body>
<section class="ui container">
<ul th:each="message : {messages}">
<li th:text="{message}" class="ui error message" />
</ul>
<form class="ui form" action="message" method="post">
<div class="field">
<label>Name:</label>
<input type="text" name="name" th:value="{name}">
</div>
<div class="field">
<label>Occupation:</label>
<input type="text" name="occupation" th:value="{occupation}">
</div>
<button class="ui button" type="submit">Send</button>
</form>
</section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.1/semantic.min.js"></script>
</body>
</html>
这是主页模板。 它发送带有两个输入的表单:名称和职业。 样式是使用语义 UI 库完成的。
<ul th:each="message : {messages}">
<li th:text="{message}" class="ui error message" />
</ul>
如果有任何错误消息,将显示它们。
templates/showMessage.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Message</title>
</head>
<body>
<p th:text="${message}"/>
</body>
</html>
成功处理表单后,showMessage
模板会显示一条消息。
com/zetcode/Application.java
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application
是设置 Spring Boot 应用的入口。
在本教程中,我们展示了如何在 Spring 应用中使用 flash 属性。