springboot validation参数校验的实例分析
创始人
2024-12-23 16:02:38
0次

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

1 pom依赖

 org.springframework.boot  spring-boot-starter-validation

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 * */@RestControllerAdvicepublic 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[] 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 {  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();  }}

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...