Spring REST 请求主体和参数验证示例

Spring REST 请求主体和参数验证示例

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]
}

下载源码

学习愉快!