這篇文章主要講解了“Spring Boot 2.x中JSR-303實現(xiàn)請求參數(shù)校驗的方法”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring Boot 2.x中JSR-303實現(xiàn)請求參數(shù)校驗的方法”吧!
為涼山州等地區(qū)用戶提供了全套網(wǎng)頁設計制作服務,及涼山州網(wǎng)站建設行業(yè)解決方案。主營業(yè)務為成都網(wǎng)站設計、成都網(wǎng)站建設、涼山州網(wǎng)站設計,以傳統(tǒng)方式定制建設網(wǎng)站,并提供域名空間備案等一條龍服務,秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務。我們深信只要達到每一位用戶的要求,就會得到認可,從而選擇與我們長期合作。這樣,我們也可以走得更遠!
請求參數(shù)的校驗是很多新手開發(fā)非常容易犯錯,或存在較多改進點的常見場景。比較常見的問題主要表現(xiàn)在以下幾個方面:
僅依靠前端框架解決參數(shù)校驗,缺失服務端的校驗。這種情況常見于需要同時開發(fā)前后端的時候,雖然程序的正常使用不會有問題,但是開發(fā)者忽略了非正常操作。比如繞過前端程序,直接模擬客戶端請求,這時候就會突然在前端預設的各種限制,直擊各種數(shù)據(jù)訪問接口,使得我們的系統(tǒng)存在安全隱患。
大量地使用if/else
語句嵌套實現(xiàn),校驗邏輯晦澀難通,不利于長期維護。
所以,針對上面的問題,建議服務端開發(fā)在實現(xiàn)接口的時候,對于請求參數(shù)必須要有服務端校驗以保障數(shù)據(jù)安全與穩(wěn)定的系統(tǒng)運行。同時,對于參數(shù)的校驗實現(xiàn)需要足夠優(yōu)雅,要滿足邏輯易讀、易維護的基本特點。
接下來,我們就在本篇教程中詳細說說,如何優(yōu)雅地實現(xiàn)Spring Boot服務端的請求參數(shù)校驗。
在開始動手實踐之前,我們先了解一下接下來我們將使用的一項標準規(guī)范:JSR-303
什么是JSR?
JSR是Java Specification Requests的縮寫,意思是Java 規(guī)范提案。是指向JCP(Java Community Process)提出新增一個標準化技術規(guī)范的正式請求。任何人都可以提交JSR,以向Java平臺增添新的API和服務。JSR已成為Java界的一個重要標準。
JSR-303定義的是什么標準?
JSR-303 是JAVA EE 6 中的一項子規(guī)范,叫做Bean Validation,Hibernate Validator 是 Bean Validation 的參考實現(xiàn) . Hibernate Validator 提供了 JSR 303 規(guī)范中所有內(nèi)置 constraint 的實現(xiàn),除此之外還有一些附加的 constraint。
Bean Validation中內(nèi)置的constraint
Hibernate Validator附加的constraint
在JSR-303的標準之下,我們可以通過上面這些注解,優(yōu)雅的定義各個請求參數(shù)的校驗。更多關于JSR的內(nèi)容可以參與官方文檔或參考資料中的引文[1]。
已經(jīng)了解了JSR-303之后,接下來我們就來嘗試一下,基于此規(guī)范如何實現(xiàn)參數(shù)的校驗!
讀者可以拿任何一個使用Spring Boot 2.x構建的提供RESTful API的項目作為基礎。也可以使用Spring Boot 2.x基礎教程:使用Swagger2構建強大的API文檔中構建的實驗工程作為基礎,您可以通過下面?zhèn)}庫中的chapter2-2
目錄取得:
Github:https://github.com/dyc87112/SpringBoot-Learning/tree/2.x
Gitee:https://gitee.com/didispace/SpringBoot-Learning/tree/2.x
當然,您也可以根據(jù)前文再構建一個作為復習,也是完全沒有問題的。
我們先來做一個簡單的例子,比如:定義字段不能為Null
。只需要兩步
第一步:在要校驗的字段上添加上@NotNull
注解,具體如下:
@Data @ApiModel(description="用戶實體") public class User { @ApiModelProperty("用戶編號") private Long id; @NotNull @ApiModelProperty("用戶姓名") private String name; @NotNull @ApiModelProperty("用戶年齡") private Integer age; }
第二步:在需要校驗的參數(shù)實體前添加@Valid
注解,具體如下:
@PostMapping("/") @ApiOperation(value = "創(chuàng)建用戶", notes = "根據(jù)User對象創(chuàng)建用戶") public String postUser(@Valid @RequestBody User user) { users.put(user.getId(), user); return "success"; }
完成上面配置之后,啟動應用,并用POST請求訪問localhost:8080/users/
接口,body使用一個空對象,{}
。你可以用Postman等測試工具發(fā)起,也可以使用curl發(fā)起,比如這樣:
curl -X POST \ 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": "Bad Request", "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": "Validation failed for object='user'. Error count: 2", "path": "/users/" }
其中返回內(nèi)容的各參數(shù)含義如下:
timestamp
:請求時間
status
:HTTP返回的狀態(tài)碼,這里返回400,即:請求無效、錯誤的請求,通常參數(shù)校驗不通過均為400
error
:HTTP返回的錯誤描述,這里對應的就是400狀態(tài)的錯誤描述:Bad Request
errors
:具體錯誤原因,是一個數(shù)組類型;因為錯誤校驗可能存在多個字段的錯誤,比如這里因為定義了兩個參數(shù)不能為Null
,所以存在兩條錯誤記錄信息
message
:概要錯誤消息,返回內(nèi)容中很容易可以知道,這里的錯誤原因是對user對象的校驗失敗,其中錯誤數(shù)量為2
,而具體的錯誤信息就定義在上面的errors
數(shù)組中
path
:請求路徑
請求的調(diào)用端在拿到這個規(guī)范化的錯誤信息之后,就可以方便的解析并作出對應的措施以完成自己的業(yè)務邏輯了。
在完成了上面的例子之后,我們還可以增加一些校驗規(guī)則,比如:校驗字符串的長度、校驗數(shù)字的大小、校驗字符串格式是否為郵箱等。下面我們就來定義一些復雜的校驗定義,比如:
@Data @ApiModel(description="用戶實體") public class User { @ApiModelProperty("用戶編號") private Long id; @NotNull @Size(min = 2, max = 5) @ApiModelProperty("用戶姓名") private String name; @NotNull @Max(100) @Min(10) @ApiModelProperty("用戶年齡") private Integer age; @NotNull @Email @ApiModelProperty("用戶郵箱") private String email; }
發(fā)起一個可以出發(fā)name
、age
、email
都校驗不通過的請求,比如下面這樣:
curl -X POST \ 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": "Bad Request", "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": "個數(shù)必須在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": "Validation failed for object='user'. Error count: 3", "path": "/users/" }
從errors
數(shù)組中的各個錯誤明細中,知道各個字段的defaultMessage
,可以看到很清晰的錯誤描述。
可能有讀者會問了,我的接口中是定了這么多。上一篇教程中,不是還教了如何自動生成文檔么,那么對于參數(shù)的校驗邏輯該如何描述呢?
這里要分兩種情況,Swagger自身對JSR-303有一定的支持,但是支持的并那么完善,并沒有覆蓋所有的注解的。
比如,上面我們使用的注解是可以自動生成的,啟動上面我們的實驗工程,然后訪問http://localhost:8080/swagger-ui.html
,在Models
不是,我們可以看到如下圖所示的內(nèi)容:
其中:name
和age
字段相比上一篇教程中的文檔描述,多了一些關于校驗相關的說明;而email
字段則沒有體現(xiàn)相關校驗說明。目前,Swagger共支持以下幾個注解:@NotNull
、@Max
、@Min
、@Size
、@Pattern
。在實際開發(fā)過程中,我們需要分情況來處理,對于Swagger支自動生成的可以利用原生支持來產(chǎn)生,如果有部分字段無法產(chǎn)生,則可以在@ApiModelProperty
注解的描述中他,添加相應的校驗說明,以便于使用方查看。
當請求參數(shù)校驗出現(xiàn)錯誤信息的時候,錯誤格式可以修改嗎?
答案是肯定的。這里的錯誤信息實際上由Spring Boot的異常處理機制統(tǒng)一組織并返回的,我們將在后面的教程中詳細介紹,Spring Boot是如何統(tǒng)一處理異常返回以及我們該如何定時異常返回。
spring-boot-starter-validation
是必須的嗎?
有讀者之前問過,看到很多教程都寫了還要引入spring-boot-starter-validation
依賴,這個依賴到底是否需要?(本篇中并沒有引入)
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-validation</artifactid> </dependency>
其實,只需要仔細看一下spring-boot-starter-validation
依賴主要是為了引入了什么,再根據(jù)當前自己使用的Spring Boot版本來判斷即可。實際上,spring-boot-starter-validation
依賴主要是為了引入下面這個依賴:
<dependency> <groupid>org.hibernate.validator</groupid> <artifactid>hibernate-validator</artifactid> <version>6.0.14.Final</version> <scope>compile</scope> </dependency>
我們可以看看當前工程的依賴中是否有它,就可以判斷是否還需要額外引入。在Spring Boot 2.1版本中,該依然其實已經(jīng)包含在了spring-boot-starter-web
依賴中,并不需要額外引入,所以您在本文中找不到這一步。
本文的完整工程可以查看下面?zhèn)}庫中的chapter2-3
目錄:
Github:https://github.com/dyc87112/SpringBoot-Learning/tree/2.x
Gitee:https://gitee.com/didispace/SpringBoot-Learning/tree/2.x
感謝各位的閱讀,以上就是“Spring Boot 2.x中JSR-303實現(xiàn)請求參數(shù)校驗的方法”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Spring Boot 2.x中JSR-303實現(xiàn)請求參數(shù)校驗的方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!
分享文章:SpringBoot2.x中JSR-303實現(xiàn)請求參數(shù)校驗的方法
文章出自:http://sd-ha.com/article24/ihhgce.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供搜索引擎優(yōu)化、標簽優(yōu)化、品牌網(wǎng)站建設、外貿(mào)建站、軟件開發(fā)、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)