对于任何一个应用而言在客户端做的数据有效性验证都不是安全有效的,这时候就要求我们在开发的时候在服务端也对数据的有效性进行验证。 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();   
    }   
    
}   
 


发布评论
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

Java NIO看这一篇就够了!知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。