前言
在实际开发中,我们无法保证客户端传来的请求都是合法的。比如一些要求必传的参数没有传递,传来的参数长度不符合要求等,这种时候如果放任不管,继续执行后续业务逻辑,很有可能就会出现意想不到的bug。
有人可能会说,这不是前端的问题吗,让前端校验去。话是这么说,但我们也不能前端校验百分百不会出现问题。并且有些请求可能也不是正规通过客户端发来的,可能是黑客恶意攻击,又或是通过postman等发来的,这些请求就不一定会“合法”了。
因此,对客户端传来的每个请求都进行必要的参数校验是十分重要的。而很多简单的校验如果都需要程序员自己去写的话,就会导致代码过于冗长、繁琐。为了让校验更加简洁明了,spring为我们提供了validation工具类来提供各种校验方法。
一、validation常见的校验注解
空校验注解:
@null
:被注释的元素必须为null
。@notnull
:被注释的元素必须不为null
。@notblank
:被注释的字符串去掉前后空格后长度必须非零。@notempty
:被注释的字符串、集合或数组不能为空(字符串长度非零、集合大小非零)。
布尔校验注解:
@asserttrue
:被注释的元素必须为true
。@assertfalse
:被注释的元素必须为false
。
日期校验注解:
@past
:被注释的元素必须是一个过去的日期。@future
:被注释的元素必须是一个将来的日期。
数字校验注解:
@min(value)
:被注释的元素必须是一个数字,其值必须大于等于指定的最小值。@max(value)
:被注释的元素必须是一个数字,其值必须小于等于指定的最大值。@decimalmin(value)
:被注释的元素必须是一个数字,其值必须大于等于指定的最小值。@decimalmax(value)
:被注释的元素必须是一个数字,其值必须小于等于指定的最大值。
长度校验注解:
@size(max, min)
:被注释的元素(如字符串、集合、数组)的大小必须在指定的范围内。
模式匹配校验注解:
@pattern(regexp)
:被注释的元素必须符合指定的正则表达式。
邮箱校验注解:
@email
:被注释的元素必须是电子邮箱地址。
范围校验注解:
@range(min, max)
:被注释的元素必须在合适的范围内。
二、validation的简单应用
首先我们需要导入validation的依赖:
<!--validation依赖,负责参数校验--> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-validation</artifactid> </dependency>
接着在需要使用校验的类上添加@validation注解
接着主要有两种方式使用校验注解:
1、直接在对应参数上加上注解
@restcontroller @requestmapping("/user") @validation public class usercontroller { @requestmapping("/login") public result login(@size(max = 12,min = 4) string username, @pattern(regexp = "^\\s{5,16}$") string password){ //登录 return result.success(); } }
2、实体类添加校验
对于一些实体类来说,直接在参数上加注解就不太可取了,程序会无法定位到指定参数。
需要再实体类内部对应的变量上添加注解:
@data @noargsconstructor @allargsconstructor public class category { @notnull private integer id;//主键id @notempty private string categoryname;//分类名称 @notempty private string categoryalias;//分类别名 private integer createuser;//创建人id @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss") private localdatetime createtime;//创建时间 @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss") private localdatetime updatetime;//更新时间 }
接着在使用实体类的地方加上 @validated 注解,就能让这些校验生效了:
@putmapping("/update") public result update(@requestbody @validated user user){ //业务逻辑 return result.success(); }
三、分组校验
前面我们介绍了如何在实体类中添加校验注解。但是,事实上在实现不同功能时,对同一个实体类的校验规则可能是会有差异的。
比如在添加用户的场景下,用户的id值就是在存入数据库后生成的,在参数传递时自然就不是必传项;而在更新用户的场景下,我们需要通过id定位指定用户,完成信息更新操作,这时在参数传递时id就是必传项了。
这样,对id值的校验就会产生冲突了。如果将id设定为必传值,那么就会导致添加用户的操作可能出现错误。不把id设定为必传值,更新用户的操作又会出现错误。
为了应对这一问题,就可以对校验项进行分组归类。具体操作步骤如下:
在实体类内部定义相应组别接口:
public class user { //各成员变量 //添加用户类分组 public interface add extends default { } //更新用户类分组 public interface update extends default{ } }
注意:如果没有手动对校验项进行分组,其默认就在 default 组
对校验项进行分组,只需要通过groups属性指定组别即可:
@notnull(groups = update.class)
接着在校验时指定对应的分组即可:
@putmapping public result update(@requestbody @validated(user.update.class) user user){ //业务逻辑 return result.success(); }
@postmapping public result add(@requestbody @validated(user.add.class) user user){ //业务逻辑 return result.success(); }
这样就能实现不同业务场景下的多样化校验了。
四、自定义校验
实际开发中的校验规则可能是五花八门的,但官方提供的校验注解就这么多,很多时候并不能满足我们的校验需求。这时候就需要通过自定义校验注解来实现个性化的校验了。
首先需要定义一个注解:
@documented //元注解 @target(elementtype.field) //元注解 @retention(retentionpolicy.runtime) //元注解 @constraint(validatedby = {/*校验规则*/}) //自定义校验规则 public @interface state { //提供校验失败后的提示信息 string message() default "state参数的值只能是已发布或草稿"; //指定分组 class<?>[] groups() default {}; //负载 获取到state注解的附加信息 class<? extends payload>[] payload() default {}; }
接着定义一个类去实现 constraintvalidator 接口,并实现 isvalid 方法:
public class statevalidation implements constraintvalidator<state,string> { @override public boolean isvalid(string value, constraintvalidatorcontext constraintvalidatorcontext) { //返回true表示校验通过,返回false则表示校验不通过 if(value==null) return false; if(value.equals("已发布")||value.equals("草稿"))return true; return false; } }
然后就要在之前定义的注解中的@constraint中填入自定义类:
@constraint(validatedby = {statevalidation.class}) //自定义校验规则
接着就可以像使用其它校验注解一样来使用自己自定义的注解了:
那么本篇文章就到此为止了,如果觉得这篇文章对你有帮助的话,可以点一下关注和点赞来支持作者哦。如果有什么讲的不对的地方欢迎在评论区指出,希望能够和你们一起进步✊
到此这篇关于spring 参数校验validation的文章就介绍到这了,更多相关spring 参数校验validation内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论