目录
一、validation的简单使用
1、pom文件引入validation
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.5.4</version>
</dependency>
2、post请求,@RequestBody参数校验,只需要在前面加@Validated即可
@PostMapping("/test1")
public void validatedTest1(@Validated @RequestBody OrderTest orderTest) {
log.info("request={}",orderTest);
}
3、get请求,@RequestParam 参数校验使用,在类上加@Validated,参数前加对应注解,@NotBlank、@NotNull等
@Slf4j
@RestController
@RequestMapping("/validated")
@Validated
public class ValidatedTestController {
@GetMapping("/test2")
public void validatedTest2(@NotBlank @RequestParam String name) {
log.info("name={}",name);
}
}
二、validation的几个常用注解
@Data
public class OrderTest {
/**
* 常用于String类型不为空
*/
@NotBlank
public String orderNo;
/**
* NotNull可用于所有类型,不能为null
* Min最小值包含该值
* Max最大值包含该值
* 注意一般结合NotNull使用,如果没有NotNull,可以不传该值,为null时不校验最大最小值
*/
@NotNull
@Min(1)
@Max(100)
public Integer quantity;
@NotNull
@DecimalMin("0.01")
@DecimalMax("200")
public BigDecimal price;
@NotNull(message = "订单日期不能为空")
public LocalDate orderDate;
}
三、 异常捕获的两种处理方式
1、validation异常捕获配置,抛异常全局捕获处理,返回前端显示只返回message即可,不然太长不太友好,ExceptionHandler的配置如下,可参考修改
- @Validated @RequestBody中参数校验抛出异常类型为BindException.class
- @NotBlank @RequestParam中参数校验异常类型ValidationException.class
//注意修改basePackages = "com.xxx.xxx" 改为自己项目路径
@ControllerAdvice(basePackages = "com.xxx.xxx")
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public HttpResponse handlerException(HttpServletRequest request, Exception e) {
log.info("exception err",e);
return HttpResponse.error(e.getMessage());
}
@ExceptionHandler(BindException.class)
public HttpResponse handlerBindException(HttpServletRequest request, BindException e) {
log.info("argumentException err",e);
StringBuilder errMessage = new StringBuilder();
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasErrors()) {
for (FieldError fieldError : bindingResult.getFieldErrors()) {
errMessage.append(fieldError.getField()).append(fieldError.getDefaultMessage()).append(";");
}
} else {
errMessage.append(e.getMessage());
}
return HttpResponse.error(errMessage.toString());
}
@ExceptionHandler(ValidationException.class)
public HttpResponse handlerValidationException(HttpServletRequest request, ValidationException ex) {
log.error("validation error",ex);
return HttpResponse.error(ex.getMessage());
}
}
2、结合BindingResult 主动判断,此种方式不会抛出异常,需要判断hasErrors进行业务处理,是继续还是中断等
@PostMapping("/test1")
public void validatedTest1(@Validated @RequestBody OrderTest orderTest, BindingResult result) {
if (result.hasErrors()) {
log.info("errors={}",result.getAllErrors());
}
log.info("request={}",orderTest);
}
四、分组校验
1、@Validated的group分组校验
例如OrderTest中orderNo我在新插入时不要求必填,更新时要求必填如果校验呢,当然呢可以分别建两个对象进行分别验证,也可以通过group来进行分组验证
(1)、接收对象OrderTest如下加入分组,Insert.class和Update.class为两个空interface,名字自行定义修改
public interface Insert {
}
@Data
public class OrderTest {
@NotBlank(groups = Update.class)
public String orderNo;
@NotBlank(groups = {Update.class,Insert.class})
public String customerId;
@NotNull(groups = Insert.class)
@Min(1)
@Max(100)
public Integer quantity;
@NotNull
@DecimalMin("0.01")
@DecimalMax("200")
public BigDecimal price;
@NotNull(message = "订单日期不能为空")
public LocalDate orderDate;
}
(2)@Validated使用时只需要加入分组即可
@Slf4j
@RestController
@RequestMapping("/validated")
@Validated
public class ValidatedTestController {
@PostMapping("/test1")
public void validatedInsertTest1(@Validated(Insert.class) @RequestBody OrderTest orderTest) {
log.info("request={}",orderTest);
}
@PostMapping("/test1/update")
public void validatedUpdateTest1(@Validated(Update.class) @RequestBody OrderTest orderTest) {
log.info("request={}",orderTest);
}
@GetMapping("/test2")
public void validatedTest2(@NotBlank @RequestParam String name) {
log.info("name={}",name);
}
}
如果@Validated加入了分组,那么只校验对应分组的判断,结果截图如下@Validated(Update.class)只校验orderNo、customerId
@Validated(Insert.class)只校验customerId、quantity
五、@Valid嵌套校验
嵌套对象属性上加@valid即可,如果是list则在List<@Valid OrderTestDetail>,新建一个OrderTest和OrderTestDetail
@Data
public class OrderTest {
@NotBlank
public String orderNo;
@NotBlank
public String customerId;
@Valid
public OrderTestDetail orderTestDetail;
@NotNull
public List<@Valid OrderTestDetail> orderTest2List;
}
@Data
public class OrderTestDetail {
@NotBlank
private String orderNo;
@NotBlank
private String name;
}
结果验证如图
中间小插曲Cannot deserialize value of type `java.util.ArrayListccom.ssh.mydmx.dto.OrderTestDetail` from Object value (token `JsonToken.START_OBJECT`)
这个因为我是用idea中restful插件orderTest2List的传参,它默认没有加中括号[]导致