SpringBoot接口如何對參數(shù)進行校驗_第1頁
SpringBoot接口如何對參數(shù)進行校驗_第2頁
SpringBoot接口如何對參數(shù)進行校驗_第3頁
SpringBoot接口如何對參數(shù)進行校驗_第4頁
SpringBoot接口如何對參數(shù)進行校驗_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

第SpringBoot接口如何對參數(shù)進行校驗目錄前言什么是不優(yōu)雅的參數(shù)校驗實現(xiàn)案例POM請求參數(shù)封裝Controller中獲取參數(shù)綁定結果校驗結果進一步理解Validation分組校驗?@Validate和@Valid什么區(qū)別?有哪些常用的校驗?自定義validation?

前言

在以SpringBoot開發(fā)Restful接口時,對于接口的查詢參數(shù)后臺也是要進行校驗的,同時還需要給出校驗的返回信息放到上文我們統(tǒng)一封裝的結構中。那么如何優(yōu)雅的進行參數(shù)的統(tǒng)一校驗呢?

什么是不優(yōu)雅的參數(shù)校驗

后端對前端傳過來的參數(shù)也是需要進行校驗的,如果在controller中直接校驗需要用大量的ifelse做判斷

以添加用戶的接口為例,需要對前端傳過來的參數(shù)進行校驗,如下的校驗就是不優(yōu)雅的:

@RestController

@RequestMapping("/user")

publicclassUserController{

@PostMapping("add")

publicResponseEntityStringadd(Useruser){

if(user.getName()==null){

returnResponseResult.fail("usernameshouldnotbeempty");

}elseif(user.getName().length()5||user.getName().length()50){

returnResponseResult.fail("usernamelengthshouldbetween5-50");

if(user.getAge()1||user.getAge()150){

returnResponseResult.fail("invalidage");

//...

returnResponseEntity.ok("success");

}

針對這個普遍的問題,Java開者在JavaAPI規(guī)范(JSR303)定義了Bean校驗的標準validation-api,但沒有提供實現(xiàn)。

hibernatevalidation是對這個規(guī)范的實現(xiàn),并增加了校驗注解如@Email、@Length等。

SpringValidation是對hibernatevalidation的二次封裝,用于支持springmvc參數(shù)自動校驗。

接下來,我們以springboot項目為例,介紹SpringValidation的使用。

實現(xiàn)案例

本例子采用springvalidation對參數(shù)綁定進行校驗,主要給你提供參數(shù)校驗的思路。針對接口統(tǒng)一的錯誤信息(比如綁定參數(shù)檢查的錯誤)封裝請看?SpringBoot接口如何統(tǒng)一異常處理

POM

添加pom依賴:

!--/artifact/org.springframework.boot/spring-boot-starter-validation--

dependency

groupIdorg.springframework.boot/groupId

artifactIdspring-boot-starter-validation/artifactId

/dependency

請求參數(shù)封裝

單一職責,所以將查詢用戶的參數(shù)封裝到UserParam中,而不是User(數(shù)據(jù)庫實體)本身。

對每個參數(shù)字段添加validation注解約束和message。

/**

*user.

*@authorpdai

@Data

@Builder

@ApiModel(value="User",subTypes={AddressParam.class})

publicclassUserParamimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@NotEmpty(message="couldnotbeempty")

privateStringuserId;

@NotEmpty(message="couldnotbeempty")

@Email(message="invalidemail")

privateStringemail;

@NotEmpty(message="couldnotbeempty")

@Pattern(regexp="^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$",message="invalidID")

privateStringcardNo;

@NotEmpty(message="couldnotbeempty")

@Length(min=1,max=10,message="nicknameshouldbe1-10")

privateStringnickName;

@NotEmpty(message="couldnotbeempty")

@Range(min=0,max=1,message="sexshouldbe0-1")

privateintsex;

@Max(value=100,message="Pleaseinputvalidage")

privateintage;

@Valid

privateAddressParamaddress;

}

Controller中獲取參數(shù)綁定結果

使用@Valid或者@Validate注解,參數(shù)校驗的值放在BindingResult中

/**

*@authorpdai

@Slf4j

@Api(value="UserInterfaces",tags="UserInterfaces")

@RestController

@RequestMapping("/user")

publicclassUserController{

*http://localhost:8080/user/add.

*@paramuserParamuserparam

*@returnuser

@ApiOperation("AddUser")

@ApiImplicitParam(name="userParam",type="body",dataTypeClass=UserParam.class,required=true)

@PostMapping("add")

publicResponseEntityStringadd(@Valid@RequestBodyUserParamuserParam,BindingResultbindingResult){

if(bindingResult.hasErrors()){

ListObjectErrorerrors=bindingResult.getAllErrors();

errors.forEach(p-{

FieldErrorfieldError=(FieldError)p;

log.error("InvalidParameter:object-{},field-{},errorMessage-{}",fieldError.getObjectName(),fieldError.getField(),fieldError.getDefaultMessage());

returnResponseEntity.badRequest().body("invalidparameter");

returnResponseEntity.ok("success");

}

校驗結果

POST訪問添加User的請求

后臺輸出參數(shù)綁定錯誤信息:(包含哪個對象,哪個字段,什么樣的錯誤描述)

2025-09-1610:37:05.173ERROR21216---[nio-8080-exec-8]t.p.s.v.controller.UserController:InvalidParameter:object-userParam,field-nickName,errorMessage-couldnotbeempty

2025-09-1610:37:05.176ERROR21216---[nio-8080-exec-8]t.p.s.v.controller.UserController:InvalidParameter:object-userParam,field-email,errorMessage-couldnotbeempty

2025-09-1610:37:05.176ERROR21216---[nio-8080-exec-8]t.p.s.v.controller.UserController:InvalidParameter:object-userParam,field-cardNo,errorMessage-couldnotbeempty

(本例只是springboot-validation的簡單用例,針對接口統(tǒng)一的錯誤信息封裝請看?SpringBoot接口如何統(tǒng)一異常處理

進一步理解

我們再通過一些問題來幫助你更深入理解validation校驗。@pdai

Validation分組校驗?

上面的例子中,其實存在一個問題,UserParam既可以作為addUser的參數(shù)(id為空),又可以作為updateUser的參數(shù)(id不能為空),這時候怎么辦呢?分組校驗登場。

@Data

@Builder

@ApiModel(value="User",subTypes={AddressParam.class})

publicclassUserParamimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@NotEmpty(message="couldnotbeempty")//這里定為空,對于addUser時是不合適的

privateStringuserId;

}

這時候可以使用Validation分組

先定義分組(無需實現(xiàn)接口)

publicinterfaceAddValidationGroup{

publicinterfaceEditValidationGroup{

}

在UserParam的userId字段添加分組

@Data

@Builder

@ApiModel(value="User",subTypes={AddressParam.class})

publicclassUserParamimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@NotEmpty(message="{user.msg.userId.notEmpty}",groups={EditValidationGroup.class})//這里

privateStringuserId;

}

controller中的接口使用校驗時使用分組

PS:需要使用@Validated注解

@Slf4j

@Api(value="UserInterfaces",tags="UserInterfaces")

@RestController

@RequestMapping("/user")

publicclassUserController{

*http://localhost:8080/user/add.

*@paramuserParamuserparam

*@returnuser

@ApiOperation("AddUser")

@ApiImplicitParam(name="userParam",type="body",dataTypeClass=UserParam.class,required=true)

@PostMapping("add")

publicResponseEntityUserParamadd(@Validated(AddValidationGroup.class){

returnResponseEntity.ok(userParam);

*http://localhost:8080/user/add.

*@paramuserParamuserparam

*@returnuser

@ApiOperation("EditUser")

@ApiImplicitParam(name="userParam",type="body",dataTypeClass=UserParam.class,required=true)

@PostMapping("edit")

publicResponseEntityUserParamedit(@Validated(EditValidationGroup.class){

returnResponseEntity.ok(userParam);

}

@Validate和@Valid什么區(qū)別?

細心的你會發(fā)現(xiàn),上個例子中用的是@Validate,而不是@Valid,那它們之間的區(qū)別是什么呢?

在檢驗Controller的入?yún)⑹欠穹弦?guī)范時,使用@Validated或者@Valid在基本驗證功能上沒有太多區(qū)別。但是在分組、注解地方、嵌套驗證等功能上兩個有所不同:

@Validated:提供了一個分組功能,可以在入?yún)Ⅱ炞C時,根據(jù)不同的分組采用不同的驗證機制,這個網(wǎng)上也有資料,不詳述。@Valid:作為標準JSR-303規(guī)范,還沒有吸收分組的功能。

@Validated:可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上

@Valid:可以用在方法、構造函數(shù)、方法參數(shù)和成員屬性(字段)上

比如本文例子中的address是user的一個嵌套屬性,只能用@Valid

@Data

@Builder

@ApiModel(value="User",subTypes={AddressParam.class})

publicclassUserParamimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

@Valid//這里只能用@Valid

privateAddressParamaddress;

}

有哪些常用的校驗?

從以下三類理解。

JSR303/JSR-349:JSR303是一項標準,只提供規(guī)范不提供實現(xiàn),規(guī)定一些校驗規(guī)范即校驗注解,如@Null,@NotNull,@Pattern,位于javax.validation.constraints包下。JSR-349是其的升級版本,添加了一些新特性。

@AssertFalse被注釋的元素只能為false

@AssertTrue被注釋的元素只能為true

@DecimalMax被注釋的元素必須小于或等于{value}

@DecimalMin被注釋的元素必須大于或等于{value}

@Digits被注釋的元素數(shù)字的值超出了允許范圍(只允許在{integer}位整數(shù)和{fraction}位小數(shù)范圍內(nèi))

@Email被注釋的元素不是一個合法的電子郵件地址

@Future被注釋的元素需要是一個將來的時間

@FutureOrPresent被注釋的元素需要是一個將來或現(xiàn)在的時間

@Max被注釋的元素最大不能超過{value}

@Min被注釋的元素最小不能小于{value}

@Negative被注釋的元素必須是負數(shù)

@NegativeOrZero被注釋的元素必須是負數(shù)或零

@NotBlank被注釋的元素不能為空

@NotEmpty被注釋的元素不能為空

@NotNull被注釋的元素不能為null

@Null被注釋的元素必須為null

@Past被注釋的元素需要是一個過去的時間

@PastOrPresent被注釋的元素需要是一個過去或現(xiàn)在的時間

@Pattern被注釋的元素需要匹配正則表達式"{regexp}"

@Positive被注釋的元素必須是正數(shù)

@PositiveOrZero被注釋的元素必須是正數(shù)或零

@Size被注釋的元素個數(shù)必須在{min}和{max}之間

hibernatevalidation:hibernatevalidation是對這個規(guī)范的實現(xiàn),并增加了一些其他校驗注解,如@Email,@Length,@Range等等

@CreditCardNumber被注釋的元素不合法的信用卡號碼

@Currency被注釋的元素不合法的貨幣(必須是{value}其中之一)

@EAN被注釋的元素不合法的{type}條形碼

@Email被注釋的元素不是一個合法的電子郵件地址(已過期)

@Length被注釋的元素長度需要在{min}和{max}之間

@CodePointLength被注釋的元素長度需要在{min}和{max}之間

@LuhnCheck被注釋的元素${validatedValue}的校驗碼不合法,Luhn模10校驗和不匹配

@Mod10Check被注釋的元素${validatedValue}的校驗碼不合法,模10校驗和不匹配

@Mod11Check被注釋的元素${validatedValue}的校驗碼不合法,模11校驗和不匹配

@ModCheck被注釋的元素${validatedValue}的校驗碼不合法,${modType}校驗和不匹配(已過期)

@NotBlank被注釋的元素不能為空(已過期)

@NotEmpty被注釋的元素不能為空(已過期)

@ParametersScriptAssert被注釋的元素執(zhí)行腳本表達式"{script}"沒有返回期望結果

@Range被注釋的元素需要在{min}和{max}之間

@SafeHtml被注釋的元素可能有不安全的HTML內(nèi)容

@ScriptAssert被注釋的元素執(zhí)行腳本表達式"{script}"沒有返回期望結果

@URL被注釋的元素需要是一個合法的URL

@DurationMax被注釋的元素必須小于${inclusive==true'或等于':''}${days==0'':days+='天'}${hours==0'':hours+='小時'}${minutes==0'':minutes+='分鐘'}${seconds==0'':seconds+='秒'}${millis==0'':millis+='毫秒'}${nanos==0'':nanos+='納秒'}

@DurationMin被注釋的元素必須大于${inclusive==true'或等于':''}${days==0'':days+='天'}${hours==0'':hours+='小時'}${minutes==0'':minutes+='分鐘'}${seconds==0'':seconds+='秒'}${millis==0'':millis+='毫秒'}${nanos==0'':nanos+='納秒'}

springvalidation:springvalidation對hibernatevalidation進行了二次封裝,在springmvc模塊中添加了自動校驗,并將校驗信息封裝進了特定的類中

自定義validation?

如果上面的注解不能滿足我們檢驗參數(shù)的要求,我們能不能自定義校驗規(guī)則呢?可以。

packagetech.pdai.springboot.validation.group.validation.custom;

importjavax.validation.Constraint;

importjavax.validation.Payload;

importjava.lang.annotation.Documented;

importjava.lang.annotation.Retention;

importjava.lang.annotation.Target;

importstaticjava.lang.annotation.ElementType.*;

importstaticjava.lang.annotation.RetentionPolicy.RUNTIME;

@Target({METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER,TYPE_USE})

@Retention(RUNTIME)

@Document

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論