https://howtodoinjava.com/spring-restful/request-body-parameter-validation/
学习验证请求正文(发布到 Spring REST API 的 JSON)。 还使用 Hibernate 验证器 2.x 验证资源 URI 中的@PathVariable
和@RequestParam
参数。
在此 SpringRest 验证示例中,我们将在为 CRUD 示例创建的 REST API 中添加验证。
1. 使用 Hibernate 验证器的请求正文验证
1.1. Maven 依赖
pom.xml
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.16.Final</version>
</dependency>
这可传递地将对 Bean 验证 API 的依赖关系拉到javax.validation:validation-api: 2.0.1.Final
。
1.2. 启用 bean 验证
在 SpringBoot 中,如果类路径上有任何 JSR-303 实现(例如Hibernate 验证器 2.0 ),则将自动启用 Bean 验证。
如果不使用 Spring Boot,则需要添加LocalValidatorFactoryBean
。
Java 配置
@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
XML 配置
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
1.3. 添加 bean 验证注解
在模型类中添加 Bean 验证注解,该注解将存储请求正文数据,例如@NotEmpty
和@Email
。
Java 配置
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
@Entity
@Table(name = "tbl_employee")
public class Employee implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotEmpty(message = "First name must not be empty")
private String firstName;
@NotEmpty(message = "Last name must not be empty")
private String lastName;
@NotEmpty(message = "Email must not be empty")
@Email(message = "Email must be a valid email address")
private String email;
public Employee() {
}
//setters and getters
@Override
public String toString() {
return "EmployeeVO [id=" + id + ", firstName=" + firstName + ",
lastName=" + lastName + ", email=" + email + "]";
}
}
1.4. 处理ConstraintViolationException
如果发生任何验证失败,Spring 将抛出ConstraintViolationException
。 我们可以使用@ExceptionHandler
处理任何返回有意义的 JSON 错误响应的事件。
CustomExceptionHandler.java
@ControllerAdvice
@ResponseBody
public class CustomExceptionHandler extends ResponseEntityExceptionHandler
{
@ExceptionHandler(ConstraintViolationException.class)
public final ResponseEntity<ErrorResponse> handleConstraintViolation(
ConstraintViolationException ex,
WebRequest request)
{
List<String> details = ex.getConstraintViolations()
.parallelStream()
.map(e -> e.getMessage())
.collect(Collectors.toList());
ErrorResponse error = new ErrorResponse(BAD_REQUEST, details);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
}
2. 查询和路径参数验证
在 Spring REST 中,通过@PathVariable
捕获请求 URI 中的参数,并通过@RequestParam
捕获所有查询参数。
请注意,必须添加 maven 依赖项,并且应按上述说明处理ConstraintViolationException
。
2.1. 启用验证
查询和路径参数验证并不简单。 我们需要显式创建 bean MethodValidationPostProcessor
,它将处理@Validated
注解。
XML 配置
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
Java 配置
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
2.2. 向参数添加验证
- 使用如上所述的 JSR-303 注解。
- 在控制器顶部使用
@Validated
注解,因此适用于其中的所有方法。
@RestController
@RequestMapping(value = "/employee-management",
produces = { MediaType.APPLICATION_JSON_VALUE })
@Validated
public class EmployeeRESTController
{
@GetMapping("/employees/{id}")
Employee getEmployeeById(@PathVariable
@Min(value = 1, message = "id must be greater than or equal to 1")
@Max(value = 1000, message = "id must be lower than or equal to 1000") Long id)
{
return repository.findById(id)
.orElseThrow(() -> new RecordNotFoundException("Employee id '" + id + "' does no exist"));
}
}
3. 演示
3.1. 请求正文验证
API 请求 1
HTTP POST : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/
Headers:
AUTH_API_KEY: abcd123456
Content-Type: application/json
Body:
{
"firstName": "",
"lastName": "Gupta",
"email": "abc@gmail.com"
}
API 响应 1
{
"message":"BAD_REQUEST",
"details":["First name must not be empty"]
}
API 请求 2
HTTP POST : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/
Headers:
AUTH_API_KEY: abcd123456
Content-Type: application/json
Body:
{
"firstName": "",
"email": "abc@gmail.com"
}
API 响应 2
{
"message":"BAD_REQUEST",
"details":
[
"First name must not be empty",
"Last name must not be empty"
]
}
3.2. 路径参数验证
API 请求 1
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/0
Headers:
AUTH_API_KEY: abcd123456
Content-Type: application/json
API 响应 1
{
"message":"BAD_REQUEST",
"details":["id must be greater than or equal to 1"]
}
API 请求 2
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/5000
Headers:
AUTH_API_KEY: abcd123456
Content-Type: application/json
API 请求 2
{
“message”:”BAD_REQUEST”,
“details”:[“id must be lower than or equal to 1000”]
}
学习愉快!