1. 运用场景
规定前端传入的内容,否者返回对应的题提示,进一步减少脏数据的出现。不用我们自己判断数据是否合法,拿到我们想要的数据。
2. 进入maven依赖
此实例为Spring boot 2.4.5
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
3. 工具类
返回值对象
import lombok.Data; import java.util.HashMap; import java.util.Map; /** * @Description 统一返回值对象 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @Data public class R { private String msg; private Integer code; private Boolean success; private Map<String, Object> data; public static R ok(){ R r = new R(); r.setMsg("OK"); r.setSuccess(true); r.setCode(0); r.setData(new HashMap<String, Object>()); return r; } public static R error(){ R r = new R(); r.setMsg("error"); r.setSuccess(false); r.setCode(-1); return r; } public R code(Integer code){ this.code = code; return this; } public R msg(String msg){ this.msg = msg; return this; } public R success(Boolean success){ this.success = success; return this; } public R data(Map map){ this.data = map; return this; } public R data(String key,Object val){ if(this.data==null) this.data = new HashMap<String, Object>(); this.data.put(key,val); return this; } }
统一异常处理类
import com.zkq.utils.R; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import java.util.HashMap; import java.util.Map; /** * @Description 异常信息处理器 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @RestControllerAdvice @Slf4j public class ExceptionHandle { // 固定处理JSR-303 抛出的异常 @ExceptionHandler(BindException.class) public R validException(BindException e){ Map<String,String> map = new HashMap<String, String>(); e.getBindingResult().getFieldErrors().forEach((fieldError) -> { map.put(fieldError.getField(),fieldError.getDefaultMessage()); }); return R.ok().msg("参数错误!").data(map); } // 统一处理不是上面JSR-303 的错误,当然也可以细分,我在此就部分了,统一处理。 @ExceptionHandler public R error(Throwable t){ // 记录响应的错误信息 // log.error("",t.getMessage()); return R.error().msg("系统错误!"); } }
4. 代码实例
4.1 普通校验 @Valid
验证对象User
import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @Description 普通校验 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @Data public class User { @NotNull(message = "id不能为空") private Long id; @NotBlank(message = "姓名不能为空") private String name; @NotNull(message = "年龄不能为空") private Integer age; }
测试接口
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class ZkqController{ // 测试 @Valid @GetMapping("/zkq") public R zkq(@Valid User user){ return R.ok().msg("标准校验").data("user",user); } }
测试结果:
不符合规范
符合规范
4.2 分组校验 @Validated
这里我就分一组演示
创建校验器分组类
/** * @Description 校验器分组,GetGroup这个不固定可随意写 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ public interface GetGroup { }
创建校验对象
import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @Description 分组校验 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @Data public class User2 { // groups = {GetGroup.class,User.class} 可分多组这里我就分了一组,根据需求自行分组 @NotNull(message = "id不能为空",groups = GetGroup.class) private Long id; @NotBlank(message = "姓名不能为空",groups = GetGroup.class) private String name; @NotNull(message = "年龄不能为空",groups = GetGroup.class) private Integer age; }
测试接口
import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ZkqController{ // 测试 @Validated @GetMapping("/zkq2") public R zkq2(@Validated(GetGroup.class) User2 user){ return R.ok().msg("分组校验").data("user",user); } }
校验结果
不符合规范
符合校验
4.3 自定义校验器校验 @Valid
创建检验器注解@ZkqNumRange
import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*; /** * @Description 自定义校验器注解 (message和groups,payload 是必须的) * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @Documented // 支持校验的类型 Long ,Float ,Integer 暂时这三种类型,有需要可以自己扩展 @Constraint(validatedBy = {ZkqNumRangeConstraintValidatorLong.class, ZkqNumRangeConstraintValidatorFloat.class, ZkqNumRangeConstraintValidatorInteger.class}) @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE}) @Retention(RetentionPolicy.RUNTIME) public @interface ZkqNumRange { // 必须的不符合的的提示语,也可以象注解一样写{javax.validation.constraints.ZkqNumRange .message} // 但是要在 resources 创建对应的文件 ValidationMessages.properties String message() default "参数不符!"; // 必须的适用于分组校验 Class<?>[] groups() default {}; // 必须的 Class<? extends Payload>[] payload() default {}; // 这个是我们自己定义是否为必须的参数,默认为不必须 boolean required() default false; // 这个是我们自己定义的最小值,默认为 0 int min() default 0; // 这个是我们自己定义的最大值,默认为 2147483647 Integer.MAX_VALUE = 2147483647 Integer.MIN_VALUE = -2147483648 int max() default Integer.MAX_VALUE; }
定义校验器支持的类型 这里我们就写三种类型Long ,Float ,Integer 。需要其他的自己扩展
Float 校验器
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @Description 参数校验器 Float 类型 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ public class ZkqNumRangeConstraintValidatorFloat implements ConstraintValidator<ZkqNumRange, Float> { private Integer max; private Integer min; private boolean required; @Override public void initialize(ZkqNumRange constraintAnnotation) { max = constraintAnnotation.max(); min = constraintAnnotation.min(); required = constraintAnnotation.required(); } @Override public boolean isValid(Float value, ConstraintValidatorContext context) { if(required || value!=null) { if(value==null) return false; if ((min <= value) && (value<= max)) { return true; } return false; } return true; } }
Integer 校验器
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @Description 参数校验器 Integer 类型 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ public class ZkqNumRangeConstraintValidatorInteger implements ConstraintValidator<ZkqNumRange, Integer> { private Integer max; private Integer min; private boolean required; @Override public void initialize(ZkqNumRange constraintAnnotation) { max = constraintAnnotation.max(); min = constraintAnnotation.min(); required = constraintAnnotation.required(); } @Override public boolean isValid(Integer value, ConstraintValidatorContext context) { if(required || value!=null) { if(value==null) return false; if ((min <= value) && (value<= max)) { return true; } return false; } return true; } }
Long 校验器
import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @Description 参数校验器 Long 类型 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ public class ZkqNumRangeConstraintValidatorLong implements ConstraintValidator<ZkqNumRange, Long> { private Integer max; private Integer min; private boolean required; @Override public void initialize(ZkqNumRange constraintAnnotation) { max = constraintAnnotation.max(); min = constraintAnnotation.min(); required = constraintAnnotation.required(); } @Override public boolean isValid(Long value, ConstraintValidatorContext context) { if(required || value!=null) { if(value==null) return false; if ((min <= value) && (value<= max)) { return true; } return false; } return true; } }
测试对象User3
import lombok.Data; /** * @Description 自定义校验器 校验 * @Author 张凯强 * @Date Created in 2021/5/20 * @E-mail 862166318@qq.com */ @Data public class User3 { // required 默认为不必须 @ZkqNumRange(message = "id不正确!") private Long id; @ZkqNumRange(message = "钱数不正确!", required = true) private Float money; // 最大值为150 @ZkqNumRange(max = 150, message = "年龄不正确!", required = true) private Integer age; }
测试接口
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class ZkqController{ // 测试 自定义校验器 @ZkqNumRange @GetMapping("/zkq3") public R zkq2(@Valid User3 user){ return R.ok().msg("自定义校验器校验").data("user",user); } }
不符合规范
符合校验
4. 自带校验注解
我把截图放这,想看的自行研究。
也可以自行阅读校验器源码,例如 @NotNull 和 @NotBlank 区别了
@NotBlank 做了toString(),然后去空格后的长度大于0。
@NotNull 就做了 object != null
有问题质询QQ:248048521,欢迎技术交流