1. 概述
数据验证是软件开发中的关键环节,确保流入应用的数据正确且一致。验证可基于不同因素应用于任何数据类型。
在Spring中,通过内置工具和注解简化了验证流程,让我们能轻松实现健壮的验证逻辑。
本教程将学习如何在Spring中验证列表值,并探讨只允许特定值的场景。通过结合标准验证和自定义验证,我们能维护数据完整性并保障应用功能无缝运行。
2. 在Spring中配置验证
启用验证需确保在pom.xml
中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
该依赖将Hibernate Validator集成到Spring应用中。
3. 验证列表值
假设需要验证员工角色列表,每个角色必须以ROLE_
开头。
首先在Employee
DTO类中添加角色字段:
@NotEmpty(message = "角色列表不能为空")
@Valid
private List<@Pattern(regexp = "ROLE_[A-Z]+",
message = "每个角色必须以'ROLE_'开头且仅包含大写字母") String> roles;
@NotEmpty
确保列表非空,@Pattern
验证每个角色符合指定格式。
接下来在控制器类添加触发验证的方法:
@PostMapping("/validateListAtService")
public ResponseEntity<String> validateRoles(@RequestBody @Validated Employee request) {
return ResponseEntity.ok("角色验证通过!");
}
此处@Validated
注解确保Spring对Employee
对象执行验证。
最后创建全局异常处理器处理验证错误:
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleValidationException(MethodArgumentNotValidException ex) {
return ex.getBindingResult()
.getFieldErrors()
.stream()
.map(e -> e.getDefaultMessage())
.collect(Collectors.joining(","));
}
关键注解解析:
@ExceptionHandler
:指定方法处理的异常类型,此处处理@Valid
或@Validated
验证失败时抛出的MethodArgumentNotValidException
@ResponseStatus
:设置响应的HTTP状态码,此处返回400 BAD REQUEST
表示客户端数据无效MethodArgumentNotValidException
:提供验证错误详情,包括失败字段和关联错误消息
现在看一个验证失败场景:
客户端发送无效数据请求:
{
"roles": ["admin", "ROLE_ADMIN,", ""]
}
根据规则(角色必须以ROLE_
开头且非空),响应如下:
每个角色必须以'ROLE_'开头且仅包含大写字母
全局异常处理器的核心优势:确保所有验证错误统一处理,提供用户友好反馈,并消除各控制器中重复的错误处理逻辑。
4. 限制值为预定义列表
前面已学习一种列表值验证方式。现在考虑另一个场景:验证员工所属部门是否在预定义列表中。我们将创建自定义注解实现此功能。
首先创建自定义验证注解:
@Constraint(validatedBy = AllowedValuesValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface AllowedValues {
String message() default "无效值";
String[] values();
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
代码解析:
@Constraint
:指定验证逻辑的实现类(AllowedValuesValidator
)@Target
:限制注解应用位置(如字段或方法参数)@Retention
:确保注解在运行时可用于验证values
:接受预定义的允许值列表message
:验证失败时的自定义错误消息groups
和payload
:分组约束和自定义元数据的可选属性
下一步实现验证器:
public class AllowedValuesValidator implements ConstraintValidator<AllowedValues, List<String>> {
private List<String> allowedValues;
@Override
public void initialize(AllowedValues constraintAnnotation)
{
allowedValues = Arrays.asList(constraintAnnotation.values());
}
@Override
public boolean isValid(List<String> values, ConstraintValidatorContext context) {
return values != null && values.stream()
.allMatch(allowedValues::contains);
}
}
initialize()
方法获取注解中定义的允许值并存储为列表,isValid()
方法验证输入列表的所有值是否都在允许列表中,并对null
输入返回false
。
最后将自定义注解应用于表示部门的List<String>
字段:
@NotEmpty(message = "部门列表不能为空")
@AllowedValues(values = {"Management", "Software Development", "DevOps", "Architect"}, message = "提供的部门无效")
private List<String> department;
@NotEmpty
确保列表非空。自定义注解@AllowedValues
指定有效部门(如Management、Software Development等),验证失败时返回"提供的部门无效"消息。
5. 总结
本文学习了在Spring中验证列表值的方法,包括限制特定值的场景。通过@Pattern
等内置注解和自定义注解,我们能以最小代价确保应用数据完整性。@Pattern
的灵活性也使其适用于各种场景下的单个字段验证。