下面是详细讲解“SpringBoot之groups应对不同的Validation规则自定义方式”的完整攻略。
什么是Validation
Validation是指对象验证,是一种可以验证Java对象的一组功能。在Java中,我们通常使用JSR 303规范中提供的Validation API来完成对象验证。
什么是Validation groups
Validation groups是Validation API中的一种概念。它允许我们将验证规则分组,从而能够让我们针对不同的场景使用不同的验证规则。
如何自定义Validation rules with group
在Spring Boot中使用Validation API,我们可以通过自定义Validation rules with group来实现利用groups应对不同的Validation规则。
具体实现步骤如下:
- 定义Validation Group
我们需要定义出多个Validation Group。例如,我们可以定义出CreateGroup、UpdateGroup、DeleteGroup等Group,分别对应创建、更新、删除API的输入参数。定义方式如下:
```java
public interface CreateGroup { }
public interface UpdateGroup { }
public interface DeleteGroup { }
```
- 在需要进行参数验证的接口输入参数上使用@Validated注解,同时指定要进行验证的Group。例如:
java
public ResultDTO<?> create(@Validated(CreateGroup.class) @RequestBody CreateUserDTO createUserDTO) { }
- 在输入参数类上使用注解@GroupSequence,定义Group的顺序。例如:
```java
public class CreateUserDTO {
@NotNull(groups = {CreateGroup.class})
private String name;
@Min(value = 18, groups = {CreateGroup.class})
private Integer age;
@NotNull(groups = {UpdateGroup.class})
private Long id;
@GroupSequence({CreateGroup.class, UpdateGroup.class})
public interface Group { }
}
```
这样,在执行参数验证时,会按照指定的Group顺序逐个验证。
- 在需要对某个Group使用自定义验证规则时,我们需要自定义验证类,并且让它实现javax.validation.ConstraintValidator接口。例如,我们需要对CreateGroup进行自定义验证,规则为:对象长度不能小于3。实现如下:
```java
public class CreateGroupValidator implements ConstraintValidator
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
return value.toString().length() >= 3;
}
}
```
- 在需要使用自定义验证规则的属性上使用自定义注解,例如,我们需要对name属性使用自定义验证规则,实现如下:
java
@NotNull(groups = {CreateGroup.class})
@CreateGroupValidator(groups = {CreateGroup.class}, message = "长度不能小于3")
private String name;
这样,我们就成功地利用groups应对不同的Validation规则,并且实现了自定义的验证规则。下面,我来举两个简单的例子。
例子一:对输入参数进行校验
我们有一个用户管理系统,其中有一个创建用户的接口。输入参数为一个JSON格式的DTO对象,其中包含用户名和年龄两个字段。我们希望在创建用户时,能够对输入参数进行验证,避免出现不合法数据。
首先,我们引入Validation API依赖,定义出CreateGroup:
public interface CreateGroup { }
我们在输入参数类上使用注解@GroupSequence,定义Group的顺序,同时标注出要验证的属性及其规则:
@Data
@NoArgsConstructor
public class CreateUserDTO {
@NotNull(groups = {CreateGroup.class})
@Length(min = 1, max = 20, groups = {CreateGroup.class}, message = "长度必须为1-20个字符")
private String name;
@NotNull(groups = {CreateGroup.class})
@Min(value = 0, groups = {CreateGroup.class}, message = "年龄必须大于等于0")
@Max(value = 150, groups = {CreateGroup.class}, message = "年龄不能大于150")
private Integer age;
@GroupSequence({CreateGroup.class})
public interface Group { }
}
我们在控制器上加上注解@Validated,并指定创建时需要验证CreateGroup。同时,在控制器方法中在输入参数上标注@RequestBody注解:
@RestController
@RequestMapping(value = "/users")
@Validated
public class UserController {
@PostMapping
public ResultDTO<?> create(@Validated(CreateUserDTO.Group.class) @RequestBody CreateUserDTO createUserDTO) {
// 写业务代码
return new ResultDTO<>();
}
}
现在,我们来测试一下这个接口,看看它对于不合法的输入参数是否能够真正地进行校验:
- 测试数据:
json
{
"name": "",
"age": -1
}
- 发送请求,预期结果:
{
"code": "InvalidArgument",
"message": "参数错误",
"data": {
"name": [
"长度必须为1-20个字符"
],
"age": [
"年龄必须大于等于0"
]
}
}
- 测试数据:
json
{
"name": "test",
"age": 1500
}
- 发送请求,预期结果:
{
"code": "InvalidArgument",
"message": "参数错误",
"data": {
"age": [
"年龄不能大于150"
]
}
}
我们可以发现,因为设置了Validation Group,这个接口能够很好地对输入参数进行校验。
例子二:对属性进行自定义校验
我们有一个管理学校课程的系统,它包括若干个课程信息。课程信息包含了课程名称和老师名称两个字段。我们希望在创建新课程信息时,对课程名称和老师名称进行校验。其中,对于课程名称,我们希望其长度不能小于3;对于老师名称,我们希望其以"Teacher_"开头。
首先,我们引入Validation API依赖,并定义自定义Annotation:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TeacherNameValidator.class)
public @interface TeacherName {
String message() default "老师名称必须以 \"Teacher_\" 开头";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
我们实现ConstraintValidator接口:
public class TeacherNameValidator implements ConstraintValidator<TeacherName, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
return value.startsWith("Teacher_");
}
}
我们在输入参数类上定义Group,并使用@TeacherName注解标注老师名称属性:
@Data
@NoArgsConstructor
public class CourseDTO {
@NotNull(groups = {CreateGroup.class})
@Length(min = 3, max = 20, groups = {CreateGroup.class}, message = "长度必须在3-20个字符之间")
private String name;
@TeacherName(groups = {CreateGroup.class}, message = "老师名称必须以 \"Teacher_\" 开头")
private String teacher;
@GroupSequence({CreateGroup.class})
public interface Group { }
}
在控制器上加上注解@Validated,并指定创建时需要验证CreateGroup。同时,在控制器方法中在输入参数上标注@RequestBody注解:
@RestController
@RequestMapping(value = "/courses")
@Validated
public class CourseController {
@PostMapping
public ResultDTO<?> create(@Validated(CourseDTO.Group.class) @RequestBody CourseDTO courseDTO) {
// 写业务代码
return new ResultDTO<>();
}
}
现在,我们来测试一下这个接口,看看它对于不合法的输入参数是否能够真正地进行校验:
- 测试数据:
json
{
"name": "A",
"teacher": "B"
}
- 发送请求,预期结果:
{
"code": "InvalidArgument",
"message": "参数错误",
"data": {
"name": [
"长度必须在3-20个字符之间"
],
"teacher": [
"老师名称必须以 \"Teacher_\" 开头"
]
}
}
- 测试数据:
json
{
"name": "Java",
"teacher": "Teacher_Li"
}
- 发送请求,预期结果:
{
"code": "OK",
"message": "创建成功",
"data": null
}
在这个例子中,我们对多个属性进行了不同的Validation规则的自定义,而且它们都成功地被执行了。
至此,我们就完成了“SpringBoot之groups应对不同的Validation规则自定义方式”的完整攻略。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot之groups应对不同的Validation规则自定义方式 - Python技术站