spring boot怎么实现请求参数校验-mile米乐体育
spring boot怎么实现请求参数校验
这篇文章主要介绍了spring boot怎么实现请求参数校验的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇spring boot怎么实现请求参数校验文章都会有所收获,下面我们一起来看看吧。
jsr-303
在开始动手实践之前,我们先了解一下接下来我们将使用的一项标准规范:jsr-303
什么是jsr?
jsr是java specification requests的缩写,意思是java 规范提案。是指向jcp(java community process)提出新增一个标准化技术规范的正式请求。任何人都可以提交jsr,以向java平台增添新的api和服务。jsr已成为java界的一个重要标准。
jsr-303定义的是什么标准?
jsr-303 是java ee 6 中的一项子规范,叫做bean validation,hibernate validator 是 bean validation 的参考实现 . hibernate validator 提供了 jsr 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
bean validation中内置的constraint
hibernate validator附加的constraint
在jsr-303的标准之下,我们可以通过上面这些注解,优雅的定义各个请求参数的校验。更多关于jsr的内容可以参与官方文档或参考资料中的引文[1]。
动手实践
已经了解了jsr-303之后,接下来我们就来尝试一下,基于此规范如何实现参数的校验!
准备工作
读者可以拿任何一个使用spring boot 2.x构建的提供restful api的项目作为基础。也可以使用spring boot 2.x基础教程:使用swagger2构建强大的api文档中构建的实验工程作为基础,您可以通过下面仓库中的chapter2-2目录取得:
github:https://github.com/dyc87112/springboot-learning/tree/2.x
gitee:https://gitee.com/didispace/springboot-learning/tree/2.x
当然,您也可以根据前文再构建一个作为复习,也是完全没有问题的。
快速入门
我们先来做一个简单的例子,比如:定义字段不能为null。只需要两步
第一步:在要校验的字段上添加上@notnull注解,具体如下:
@data@apimodel(description="用户实体")publicclassuser{@apimodelproperty("用户编号")privatelongid;@notnull@apimodelproperty("用户姓名")privatestringname;@notnull@apimodelproperty("用户年龄")privateintegerage;}
第二步:在需要校验的参数实体前添加@valid注解,具体如下:
@postmapping("/")@apioperation(value="创建用户",notes="根据user对象创建用户")publicstringpostuser(@valid@requestbodyuseruser){users.put(user.getid(),user);return"success";}
完成上面配置之后,启动应用,并用post请求访问localhost:8080/users/接口,body使用一个空对象,{}。你可以用postman等测试工具发起,也可以使用curl发起,比如这样:
curl-xpost\http://localhost:8080/users/\-h'content-type:application/json'\-h'postman-token:72745d04-caa5-44a1-be84-ba9c115f4dfb'\-h'cache-control:no-cache'\-d'{}'
不出意外,你可以得到如下结果:
{"timestamp":"2019-10-05t05:45:19.221 0000","status":400,"error":"badrequest","errors":[{"codes":["notnull.user.age","notnull.age","notnull.java.lang.integer","notnull"],"arguments":[{"codes":["user.age","age"],"arguments":null,"defaultmessage":"age","code":"age"}],"defaultmessage":"不能为null","objectname":"user","field":"age","rejectedvalue":null,"bindingfailure":false,"code":"notnull"},{"codes":["notnull.user.name","notnull.name","notnull.java.lang.string","notnull"],"arguments":[{"codes":["user.name","name"],"arguments":null,"defaultmessage":"name","code":"name"}],"defaultmessage":"不能为null","objectname":"user","field":"name","rejectedvalue":null,"bindingfailure":false,"code":"notnull"}],"message":"validationfailedforobject='user'.errorcount:2","path":"/users/"}
其中返回内容的各参数含义如下:
timestamp:请求时间
status:http返回的状态码,这里返回400,即:请求无效、错误的请求,通常参数校验不通过均为400
error:http返回的错误描述,这里对应的就是400状态的错误描述:bad request
errors:具体错误原因,是一个数组类型;因为错误校验可能存在多个字段的错误,比如这里因为定义了两个参数不能为null,所以存在两条错误记录信息
message:概要错误消息,返回内容中很容易可以知道,这里的错误原因是对user对象的校验失败,其中错误数量为2,而具体的错误信息就定义在上面的errors数组中
path:请求路径
请求的调用端在拿到这个规范化的错误信息之后,就可以方便的解析并作出对应的措施以完成自己的业务逻辑了。
尝试一些其他校验
在完成了上面的例子之后,我们还可以增加一些校验规则,比如:校验字符串的长度、校验数字的大小、校验字符串格式是否为邮箱等。下面我们就来定义一些复杂的校验定义,比如:
@data@apimodel(description="用户实体")publicclassuser{@apimodelproperty("用户编号")privatelongid;@notnull@size(min=2,max=5)@apimodelproperty("用户姓名")privatestringname;@notnull@max(100)@min(10)@apimodelproperty("用户年龄")privateintegerage;@notnull@email@apimodelproperty("用户邮箱")privatestringemail;}
发起一个可以出发name、age、email都校验不通过的请求,比如下面这样:
curl-xpost\http://localhost:8080/users/\-h'content-type:application/json'\-h'postman-token:114db0f0-bdce-4ba5-baf6-01e5104a68a3'\-h'cache-control:no-cache'\-d'{"name":"abcdefg","age":8,"email":"aaaa"}'
我们将得到如下的错误返回:
{"timestamp":"2019-10-05t06:24:30.518 0000","status":400,"error":"badrequest","errors":[{"codes":["size.user.name","size.name","size.java.lang.string","size"],"arguments":[{"codes":["user.name","name"],"arguments":null,"defaultmessage":"name","code":"name"},5,2],"defaultmessage":"个数必须在2和5之间","objectname":"user","field":"name","rejectedvalue":"abcdefg","bindingfailure":false,"code":"size"},{"codes":["min.user.age","min.age","min.java.lang.integer","min"],"arguments":[{"codes":["user.age","age"],"arguments":null,"defaultmessage":"age","code":"age"},10],"defaultmessage":"最小不能小于10","objectname":"user","field":"age","rejectedvalue":8,"bindingfailure":false,"code":"min"},{"codes":["email.user.email","email.email","email.java.lang.string","email"],"arguments":[{"codes":["user.email","email"],"arguments":null,"defaultmessage":"email","code":"email"},[],{"defaultmessage":".*","codes":[".*"],"arguments":null}],"defaultmessage":"不是一个合法的电子邮件地址","objectname":"user","field":"email","rejectedvalue":"aaaa","bindingfailure":false,"code":"email"}],"message":"validationfailedforobject='user'.errorcount:3","path":"/users/"}
从errors数组中的各个错误明细中,知道各个字段的defaultmessage,可以看到很清晰的错误描述。
swagger文档中的体现
可能有读者会问了,我的接口中是定了这么多。上一篇教程中,不是还教了如何自动生成文档么,那么对于参数的校验逻辑该如何描述呢?
这里要分两种情况,swagger自身对jsr-303有一定的支持,但是支持的并那么完善,并没有覆盖所有的注解的。
比如,上面我们使用的注解是可以自动生成的,启动上面我们的实验工程,然后访问http://localhost:8080/swagger-ui.html,在models不是,我们可以看到如下图所示的内容:
其中:name和age字段相比上一篇教程中的文档描述,多了一些关于校验相关的说明;而email字段则没有体现相关校验说明。目前,swagger共支持以下几个注解:@notnull、@max、@min、@size、@pattern。在实际开发过程中,我们需要分情况来处理,对于swagger支自动生成的可以利用原生支持来产生,如果有部分字段无法产生,则可以在@apimodelproperty注解的描述中他,添加相应的校验说明,以便于使用方查看。
番外:也许你会有这些疑问
当请求参数校验出现错误信息的时候,错误格式可以修改吗?
答案是肯定的。这里的错误信息实际上由spring boot的异常处理机制统一组织并返回的,我们将在后面的教程中详细介绍,spring boot是如何统一处理异常返回以及我们该如何定时异常返回。
spring-boot-starter-validation是必须的吗?
有读者之前问过,看到很多教程都写了还要引入spring-boot-starter-validation依赖,这个依赖到底是否需要?(本篇中并没有引入)
其实,只需要仔细看一下spring-boot-starter-validation依赖主要是为了引入了什么,再根据当前自己使用的spring boot版本来判断即可。实际上,spring-boot-starter-validation依赖主要是为了引入下面这个依赖:
我们可以看看当前工程的依赖中是否有它,就可以判断是否还需要额外引入。在spring boot 2.1版本中,该依然其实已经包含在了spring-boot-starter-web依赖中,并不需要额外引入,所以您在本文中找不到这一步。
关于“spring boot怎么实现请求参数校验”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“spring boot怎么实现请求参数校验”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道。