zoukankan      html  css  js  c++  java
  • spring boot validation参数校验

         对于任何一个应用而言在客户端做的数据有效性验证都不是安全有效的,这时候就要求我们在开发的时候在服务端也对数据的有效性进行验证。 Spring Boot自身对数据在服务端的校验有一个比较好的支持,它能将我们提交到服务端的数据按照我们事先的约定进行数据有效性验证。

    1 pom依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    2 校验使用实例

    • 配置要验证的请求实体
    public class User {
        @Null
        private Long id;
        @NotBlank
        private String name;
        @Email
        private String email;
       // 省略getter和setter
    }
    • 控制器方法配置
    @PostMapping("/addUser")
    public String addUser(@Valid @RequestBody User user){
        ...
    }
    • 校验失败统一处理

          校验失败时将抛出MethodArgumentNotValidException异常

    /**
     * 全局Exception处理
     * 
     * @author liusq
     *
     */
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        @SuppressWarnings("rawtypes")
        @ExceptionHandler(value = Exception.class)
        public ResponseEntity handle(Exception e) {
            if (e instanceof MethodArgumentNotValidException) {
                BindingResult bindingResult = ((MethodArgumentNotValidException) e).getBindingResult();
                if (bindingResult.hasErrors() && bindingResult.hasFieldErrors()) {
                    FieldError fieldError = bindingResult.getFieldError();
                    BodyValidStatus bodyValidStatus = new BodyValidStatus.Builder().code("0009")
                            .message(fieldError.getDefaultMessage())
                            .field(fieldError.getField()).build();
                    LOGGER.warn(bodyValidStatus.getMessage() + e);
                    return new ResponseEntity<>(bodyValidStatus, HttpStatus.OK);
                } else {
                    bodyStatus = DataUtil.bodyStatus("0009");
                }
            } else {
                bodyStatus = DataUtil.bodyStatus(Constants.ERROR_CODE);
            }
            LOGGER.error(bodyStatus.getMessage() + e);
            return new ResponseEntity<>(bodyStatus, HttpStatus.OK);
        }
    }
    public class BodyValidStatus {
        // 错误代码
        private String code;
        // 错误代码解释
        private String message;
        // 错误字段
        private String field;
    
        public BodyValidStatus() {
        }
    
        public BodyValidStatus(String code, String message, String field) {
            this.code = code;
            this.message = message;
            this.field = field;
        }
    
        private BodyValidStatus(Builder builder) {
            setCode(builder.code);
            setMessage(builder.message);
            setField(builder.field);
        }
    
        public String getCode() {
            return code;
        }
    
        public void setCode(String code) {
            this.code = code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        public String getField() {
            return field;
        }
    
        public void setField(String field) {
            this.field = field;
        }
    
        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this);
        }
    
        public static final class Builder {
            private String code;
            private String message;
            private String field;
    
            public Builder() {
            }
    
            public Builder code(String val) {
                code = val;
                return this;
            }
    
            public Builder message(String val) {
                message = val;
                return this;
            }
    
            public Builder field(String val) {
                field = val;
                return this;
            }
    
            public BodyValidStatus build() {
                return new BodyValidStatus(this);
            }
        }
    }

    3 验证注解详解

    验证注解

    验证的数据类型

    说明

    空检查

    @Null

    任意类型

    验证注解的元素值是null

    @NotNull

    任意类型

    验证注解的元素不是null

    @NotBlank

    CharSequence子类型(CharBuffer、String、StringBuffer、StringBuilder)

    验证注解的元素值不为空(不为null、去除首尾空格后长度不为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首尾空格

    @NotEmpty

    CharSequence子类型、Collection、Map、数组

    验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

    Boolean检查

    @AssertFalse

    Boolean,boolean

    验证注解的元素值是false

    @AssertTrue

    Boolean,boolean

    验证注解的元素值是true

    长度检查

    @Size(min=下限, max=上限)

    字符串、Collection、Map、数组等

    验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小

    @Length(min=下限, max=上限)

    CharSequence子类型

    验证注解的元素值长度在min和max区间内

    日期检查

    @Past

    java.util.Date,java.util.Calendar;Joda Time类库的日期类型

    验证注解的元素值(日期类型)比当前时间早

    @Future

    与@Past要求一样

    验证注解的元素值(日期类型)比当前时间晚

    数值检查

    @MIN(value=值)

    BigDecimal,BigInteger, byte,short, int, long,等任何Number或CharSequence(存储的是数字)子类型

    验证注解的元素值大于等于@Min指定的value值

    @MAX(value=值)

    和@Min要求一样

    验证注解的元素值小于等于@Max指定的value值

    @DecimalMin(value=值)

    和@Min要求一样

    验证注解的元素值大于等于@ DecimalMin指定的value值

    @DecimalMax(value=值)

    和@Min要求一样

    验证注解的元素值小于等于@ DecimalMax指定的value值

    @Digits(integer=整数位数, fraction=小数位数)

    和@Min要求一样

    验证注解的元素值的整数位数和小数位数上限

    @Range(min=最小值, max=最大值)

    BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型

    验证注解的元素值在最小值和最大值之间

    其他检查

    @Valid

    任何非原子类型

    指定递归验证关联的对象;如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

    @Pattern(regexp=正则表达式,flag=标志的模式)

    CharSequence的子类型

    验证注解的元素值与指定的正则表达式匹配

    @Email(regexp=正则表达式,flag=标志的模式)

    CharSequence的子类型

    验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式

    @CreditCardNumber

    CharSequence的子类型

    验证注解元素值是信用卡卡号

    @ScriptAssert(lang= ,script=)

    业务类

    校验复杂的业务逻辑

    4 自定义验证注解和验证规则

    import java.lang.annotation.ElementType;  
    import java.lang.annotation.Retention;  
    import java.lang.annotation.RetentionPolicy;  
    import java.lang.annotation.Target;  
       
    import javax.validation.Constraint;  
    import javax.validation.Payload;  
       
    import com.xxx.xxx.constraint.impl.MoneyValidator;  
       
    @Target({ElementType.FIELD, ElementType.METHOD})  
    @Retention(RetentionPolicy.RUNTIME)  
    @Constraint(validatedBy=MoneyValidator.class)  
    public @interface Money {  
         
        String message() default"不是金额形式";  
         
        Class<?>[] groups() default {};  
         
        Class<? extends Payload>[] payload() default {};  
       
    }  
    import java.util.regex.Pattern;  
       
    import javax.validation.ConstraintValidator;  
    import javax.validation.ConstraintValidatorContext;  
       
    import com.xxx.xxx.constraint.Money;  
       
    public class MoneyValidator implements ConstraintValidator<Money, Double> {  
       
        private String moneyReg = "^\d+(\.\d{1,2})?$";//表示金额的正则表达式  
        private Pattern moneyPattern = Pattern.compile(moneyReg);  
         
        public void initialize(Money money) {  
           // TODO Auto-generated method stub  
            
        }  
       
        public boolean isValid(Double value, ConstraintValidatorContext arg1) {  
           // TODO Auto-generated method stub  
           if (value == null)  
               return true;  
           return moneyPattern.matcher(value.toString()).matches();  
        }  
       
    }  
     
  • 相关阅读:
    硬件笔记之删除UEFI启动项
    高数学习笔记之向量内积(点乘)和外积(叉乘)概念及几何意义
    机器学习笔记之聚类算法K-Means
    机器学习之聚类算法Mean Shift
    机器学习笔记之聚类算法 层次聚类 Hierarchical Clustering
    机器学习笔记之决策树分类Decision Tree
    机器学习笔记之一步步教你轻松学关联规则Apriori算法
    机器学习笔记之占一步步教你学K-means
    完美解决github访问速度慢
    ROS2 cartographer 保存地图
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/11551912.html
Copyright © 2011-2022 走看看