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

spring boot validation参数校验的更多相关文章

  1. Spring基础系列-参数校验

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9953744.html Spring中使用参数校验 概述 ​ JSR 303中提出了Bea ...

  2. spring注解式参数校验

    很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者返回异常时的校验信息,在代码中相当冗长,今天我们就来学习spring注解式参数校验. 其实就是:hibernate的validator. 开始啦. ...

  3. spring boot 输入参数统一校验

    1 引入spring boot validate    maven 依赖 <!-- 验证 --> <dependency> <groupId>org.hiberna ...

  4. Kotlin + Spring Boot 请求参数验证

    编写 Web 应用程序的时候,经常要做的事就是要对前端传回的数据进行简单的验证,比如是否非空.字符长度是否满足要求,邮箱格式是否正确等等.在 Spring Boot 中,可以使用 Bean Valid ...

  5. 【spring】-- jsr303参数校验器

    一.为什么要进行参数校验? 当我们在服务端控制器接受前台数据时,肯定首先要对数据进行参数验证,判断参数是否为空?是否为电话号码?是否为邮箱格式?等等. 这里有个问题要注意: 前端代码一般上会对这些数据 ...

  6. Spring boot 配置文件参数映射到配置类属性

    [参考文章]:SpringBoot之@EnableConfigurationProperties分析 [参考文章]:在Spring Boot中使用 @ConfigurationProperties 注 ...

  7. javax.validation参数校验

    在实体字段加注解: /** * 机构名称 */ @ApiParam(name = "orgName", value = "机构名称") @Size(max = ...

  8. Spring Boot 构造器参数绑定,越来越强大了!

    在之前的文章:Spring Boot读取配置的几种方式,我介绍到 Spring Boot 中基于 Java Bean 的参数绑定,在一个 Java Bean 类上用 @ConfigurationPro ...

  9. 解放生产力:Spring Boot的注解校验

    关于对象入参的校验,我们可能第一个想到的就是在Controller层或者Service层增加很多if else的判断,如: if (user.getPassword() == "" ...

随机推荐

  1. 自学Python编程的第十天(希望有IT大牛看见的指点小弟我,万分感谢)---------来自苦逼的转行人

    2019-09-20-23:24:15 今天逛论坛.逛知识星球时.逛b站up主时,都说到低学历,非科班的人最好不要去自学Python 他们都说:如果我们学python是为了找工作,最好不要把pytho ...

  2. 【夯实基础】- Java中的fail-fast机制

    转载自:Java中的fail-fast机制 遍历删除List中的元素有很多种方法,当运用不当的时候就会产生问题.下面主要看看以下几种遍历删除List中元素的形式: 1.通过普通的for删除删除符合条件 ...

  3. webpack4引入JQuery的两种方法

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_36185028/artic ...

  4. 两个数组的交集 II

    题纲 给定两个数组,编写一个函数来计算它们的交集. 示例 : 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出: [4,9] 说明: 输出结果中每个元素出现的次数 ...

  5. 关于小程序授权地理位置(wx.getLocation + 用户体验)

    wx.getLocation 如果用户曾点击过一次 “确认授权” , 那么再次调用该接口时将不会出现弹出框(可以直接拿到经纬度) 关于用户体验: 在 onLoad 中判断: 如果用户之前“没有触发过“ ...

  6. C++中string的实现原理

    C++中string的实现原理 背景 当我刚开始学习C++,对C还是有一部分的了解,所以以C的思维去学C++,导致我很长一段时间的学习都处于一个懵逼的状态,C++的各种特性,标准库,模板还有版本的迭代 ...

  7. Python入门篇-类型注解

    Python入门篇-类型注解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.函数定义的弊端 1>.动态语言很灵活,但是这种特性也是弊端 Python是动态语言,变量随时可 ...

  8. git及github使用

    1.git安装 widows: 可以去git官网下载安装 ubantu : 使用命令 sudo apt-get install git 进行安装 2.git启动 widows: 首先去到需要建立git ...

  9. python deque的内在实现 本质上就是双向链表所以用于stack、队列非常方便

    How collections.deque works? Cosven     前言:在 Python 生态中,我们经常使用 collections.deque 来实现栈.队列这些只需要进行头尾操作的 ...

  10. python笔记37-史上最好用的发邮件zmail

    简介 python发邮件之前用的是smtplib,代码太过于复杂,学习成本大,并且很多人学不会.之前专门写过一篇https://www.cnblogs.com/yoyoketang/p/7277259 ...