ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Spring REST 请求主体和参数验证示例 > [https://howtodoinjava.com/spring-restful/request-body-parameter-validation/](https://howtodoinjava.com/spring-restful/request-body-parameter-validation/) 学习**验证请求正文**(发布到 Spring REST API 的 JSON)。 还使用 [Hibernate 验证器 2.x](https://beanvalidation.org/2.0/) 验证资源 URI 中的`@PathVariable`和`@RequestParam`参数。 在此 **SpringRest 验证示例**中,我们将在为 [CRUD 示例](https://howtodoinjava.com/spring-restful/spring-rest-crud-jpa-example/)创建的 [REST API](http://restfulapi.net/) 中添加验证。 ## 1\. 使用 Hibernate 验证器的请求正文验证 #### 1.1. Maven 依赖 `pom.xml` ```java <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](https://howtodoinjava.com/spring-boot-tutorials/) 中,如果类路径上有任何 **JSR-303** 实现(例如[Hibernate 验证器 2.0](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/) ),则将自动启用 Bean 验证。 如果不使用 Spring Boot,则需要添加[`LocalValidatorFactoryBean`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/beanvalidation/LocalValidatorFactoryBean.html)。 `Java 配置` ```java @Bean public javax.validation.Validator localValidatorFactoryBean() { return new LocalValidatorFactoryBean(); } ``` `XML 配置` ```java <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> ``` #### 1.3. 添加 bean 验证注解 在模型类中添加 Bean 验证注解,该注解将存储请求正文数据,例如`@NotEmpty`和`@Email`。 `Java 配置` ```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`](https://javaee.github.io/javaee-spec/javadocs/javax/validation/ConstraintViolationException.html)。 我们可以使用[`@ExceptionHandler`](https://howtodoinjava.com/spring-core/spring-exceptionhandler-annotation/)处理任何返回有意义的 JSON 错误响应的事件。 `CustomExceptionHandler.java` ```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 配置` ```java <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> ``` `Java 配置` ```java @Bean public MethodValidationPostProcessor methodValidationPostProcessor() { return new MethodValidationPostProcessor(); } ``` #### 2.2. 向参数添加验证 * 使用如上所述的 JSR-303 注解。 * 在控制器顶部使用`@Validated`注解,因此适用于其中的所有方法。 ```java @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` ```java 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` ```java { "message":"BAD_REQUEST", "details":["First name must not be empty"] } ``` `API 请求 2` ```java 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` ```java { "message":"BAD_REQUEST", "details": [ "First name must not be empty", "Last name must not be empty" ] } ``` #### 3.2. 路径参数验证 `API 请求 1` ```java HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/0 Headers: AUTH_API_KEY: abcd123456 Content-Type: application/json ``` `API 响应 1` ```java { "message":"BAD_REQUEST", "details":["id must be greater than or equal to 1"] } ``` `API 请求 2` ```java HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/5000 Headers: AUTH_API_KEY: abcd123456 Content-Type: application/json ``` `API 请求 2` ```java { “message”:”BAD_REQUEST”, “details”:[“id must be lower than or equal to 1000”] } ``` [下载源码](https://howtodoinjava.com/wp-content/downloads/SpringRestExample.zip) 学习愉快!