统一校验
作者:互联网
此文代码托管地址: https://gitee.com/ZomiCC/code/tree/master/validate
我们平时都会碰到很多通用校验的场景:比如字段非空校验、字段长度校验等等。如下所示:
- @Null:被注释的元素必须为null
- @NotNull:被注释的元素不能为null
- @AssertTrue:该字段只能为true
- @AssertFalse:该字段的值只能为false
- @Min(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值
- @Max(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值
- @DecimalMin(“value”):被注释的元素必须是一个数字,验证小数的最小值
- @DecimalMax(“value”):被注释的元素必须是一个数字,验证小数的最大值
- @Size(max,min):查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等
- @Past:被注释的元素必须是一个过去的日期
- @Future:被注释的元素必须是一个将来的日期
- @Pattern(regexp = “[abc]”):被注释的元素必须符合指定的正则表达式。
- @Email:被注释的元素必须是电子邮件地址
- @Length(max=5,min=1,message=“长度在1~5”):检查所属的字段的长度是否在min和max之间,只能用于字符串
- @NotEmpty:被注释的字符串必须非空
- @Range:被注释的元素必须在合适的范围内
- @NotBlank:不能为空,检查时会将空格忽略
- @NotEmpty:不能为空,这里的空是指空字符串
具体是如何实现的呢,话不多说,直接看使用方式。
两种校验方式
一、@Validated + BindingResult controller校验
请求实体与BindingResult一一对应。
依赖的注解:
展开
<!-- valid校验 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<!-- 想要BindResult生效,这个依赖一定要有 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
点击查看代码
@Data
@ToString
public class ReqDTO {
@NotBlank(message = "param1不能为空")
private String param1;
@NotBlank(message = "param2不能为空")
private String param2;
@NotBlank(message = "param3不能为空")
private String param3;
}
点击查看代码
@PostMapping("/param1")
public String param1(@Validated @RequestBody ReqDTO reqDTO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
return fieldError.getDefaultMessage();
}
return "success";
}
响应
二、自定义Validator校验工具类
不局限于controller层,在任何地方都可以使用。
工具类:
点击查看代码
package com.example.validate.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Component
public class ParamCheckUtil {
private static Validator validator;
@Autowired
private Validator injectValidator;
@PostConstruct
public void preInit() {
validator = injectValidator;
}
public static <T> String checkByGroupsGetOneMessage(T t, Class<?>... groups) {
if (t == null) {
return null;
}
Set<ConstraintViolation<T>> validate = validator.validate(t, groups);
if (validate.size() == 0) {
return null;
}
return validate.stream().findFirst().get().getMessage();
}
public static <T> String checkByGroupsGetAllMessage(T t, Class<?>... groups) {
if (t == null) {
return null;
}
Set<ConstraintViolation<T>> validate = validator.validate(t, groups);
if (validate.size() == 0) {
return null;
}
List<String> msgList = new ArrayList<>();
validate.forEach(cv -> msgList.add(cv.getMessage()));
return String.join(";", msgList);
}
}
点击查看代码
@PostMapping("/param2")
public String param2(@RequestBody ReqDTO reqDTO) {
String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);
if (message != null) {
return message;
}
return "success";
}
其他扩展校验
一、分组校验
当一个实体类应用于多个场景的请求入参时,对入参要求又不一样,我们没必要每次都新建一个冗余的实体类。那怎么办呢,可以给校验属性添加上分组。默认分组是Default。
实体类:
点击查看代码
@Data
@ToString
public class GroupReqDTO {
@NotBlank(message = "param1不能为空")
private String param1;
@NotBlank(message = "param2不能为空", groups = A.class)
private String param2;
@NotBlank(message = "param3不能为空", groups = B.class)
private String param3;
public interface A {}
public interface B {}
}
点击查看代码
@PostMapping("/param4")
public String param4(@Validated({GroupReqDTO.A.class}) @RequestBody GroupReqDTO reqDTO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
return fieldError.getDefaultMessage();
}
return "success";
}
二、嵌套校验
当存在嵌套引用对象时,可以使用嵌套校验。嵌套类型需要使用@Valid注解标识。
实体类:
点击查看代码
@Data
public class NestedReqDTO {
@NotBlank(message = "param1不能为空")
private String param1;
@NotBlank(message = "param2不能为空")
private String param2;
@NotBlank(message = "param3不能为空")
private String param3;
@Valid
@NotNull(message = "param4不能为空")
private OtherEntity param4;
@Data
class OtherEntity {
@NotBlank(message = "属性1不能为空")
private String property1;
}
}
点击查看代码
@PostMapping("/param5")
public String param5(@Validated @RequestBody NestedReqDTO reqDTO, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
assert fieldError != null;
return fieldError.getDefaultMessage();
}
return "success";
}
三、复杂关联校验
借助DefaultGroupSequenceProvider,可以实现属性间依赖关系的复杂校验。具体实现参考如下代码:
实体类:
点击查看代码
@Data
@ToString
@GroupSequenceProvider(MyGroupSequenceProvider.class)
public class MutiReqDTO {
@NotBlank(message = "param1不能为空")
private String param1;
@NotBlank(message = "param2不能为空")
private String param2;
@NotBlank(message = "当param2为1时,param3不能为空", groups = Param2.class)
private String param3;
public interface Param2 {}
}
分组配置器:
点击查看代码
public class MyGroupSequenceProvider implements DefaultGroupSequenceProvider<MutiReqDTO> {
@Override
public List<Class<?>> getValidationGroups(MutiReqDTO mutiReqDTO) {
List<Class<?>> classes = new ArrayList<>();
classes.add(MutiReqDTO.class);
if (mutiReqDTO == null) {
return classes;
}
// 如果param2参数为“1”,则需要校验param3
if ("1".equals(mutiReqDTO.getParam2())) {
classes.add(MutiReqDTO.Param2.class);
}
return classes;
}
}
controller测试:
点击查看代码
@PostMapping("/param3")
public String param3(@RequestBody MutiReqDTO reqDTO) {
String message = ParamCheckUtil.checkByGroupsGetAllMessage(reqDTO);
if (message != null) {
return message;
}
return "success";
}
验证效果:
标签:return,String,校验,private,为空,message,public,统一 来源: https://www.cnblogs.com/zomicc/p/16652157.html