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,欢迎技术交流