在日常开发中,我们有时候需要对一些参数进行校验,此时需要书写大量的逻辑判断,会显得代码比较冗余(如图所示)。
此时可以使用如下注解方式来简化代码。
Valid注解方式
引入相关依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>3.2.1</version>
</dependency>
java
@Data
public class ModifyNameReq {
@NotBlank
@Size(max = 6,message = "名称不能太长哦!")
private String name;
@NotBlank
@Size(max = 6,message = "名称不能太长哦!")
private String address;
@NotBlank
private String img;
}
@Valid要加上,否则会没有效果,校验不了
java
@RestController
public class EurekaServerController {
@PostMapping("test")
public String save(@Valid @RequestBody ModifyNameReq nameReq){
return "OK";
}
}
使用postman
进行测试
此时如果不配置异常处理器,会出现如下错误。所以为了更好的显示和更友好的提醒用户可以配置异常处理器。
异常处理器
java
@RestControllerAdvice // 监听打了@RestController注解的Controller
public class GlobalExceptionHandler {
/**
* validation参数校验异常
*/
@ExceptionHandler(value = MethodArgumentNotValidException.class) // 监听该类型的错误
public ApiResult<?> methodArgumentNotValidException(MethodArgumentNotValidException exception){
StringBuilder errorMsg = new StringBuilder();
exception.getBindingResult().getFieldErrors() // 获取所有错误字段信息
.forEach(item->errorMsg.append(item.getField()).append(item.getDefaultMessage()));
return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(),errorMsg.substring(0,errorMsg.length() -1));
}
}
上述代码中,大家只需要了解如何获取错误字段信息即可,前面的ApiResult只是用来封装返回给前端结果的工具类
此时有的小伙伴就又会说了,那我如果是对象里面包含了一个对象,也需要进行数据的校验怎么办呢?此时我们就可以采取下面的方式了。
java
@Data
public class ModifyNameReq {
@NotBlank
@Size(max = 6,message = "名称不能太长哦!")
private String name;
@NotBlank
private String img;
@Valid // 这个注解会触发Address对象的校验
private Address address;
}
java
@Data
public class Address {
@NotBlank(message = "城市不能为空")
@Size(max = 50, message = "城市名称不能超过50个字符")
private String city;
@NotBlank(message = "街道不能为空")
@Size(max = 100, message = "街道名称不能超过100个字符")
private String street;
}
此时我们并没有输入street
字段,此时看看会出现什么错误呢?
大家可以很清晰地看见我们的嵌套的校验生效了。
此时又有小伙伴们说了,那么如果对象里面包含一个集合对象呢
java
@Data
public class ModifyNameReq {
@NotBlank
@Size(max = 6,message = "名称不能太长哦!")
private String name;
@NotBlank
private String img;
@Valid // 这个注解会触发Address对象的校验
private List<Address> address;
}
此时发送请求,出现的异常会跟上述异常相同。
非注解方式
在上面的示例中,ModifyNameReq
类包含了一个Address
类型的属性和一个Address
类型的列表属性。对于这两个属性,我们都使用了@Valid
注解来指示需要对它们进行校验。此外,我们还为city
、street
和name
等属性添加了其他的校验注解,如@NotNull
和@Size
。
要使用这些校验注解,还需要配置一个校验器(Validator),并在需要的时候调用它来执行校验。这通常是通过Spring框架自动完成的,但是也可以手动创建和使用Validator
实例。以下是一个简单的示例,展示了如何手动使用Validator
来校验ModifyNameReq
对象:
java
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
public class ValidationExample {
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
ModifyNameReq modifyNameReq = new ModifyNameReq();
modifyNameReq.setImg("http:132.png");
modifyNameReq.setName("手动创建使用Validator实例");
Address address = new Address();
address.setCity("北京");
modifyNameReq.setAddress(Arrays.asList(address));
Set<ConstraintViolation<ModifyNameReq>> violations = validator.validate(modifyNameReq);
if (!violations.isEmpty()) {
for (ConstraintViolation<ModifyNameReq> violation : violations) {
System.out.println(violation.getMessage());
}
} else {
System.out.println("Validation succeeded");
}
}
}
此时大家可以运行这段代码,看看会有什么信息打印出来吧。