springboot整合JSR303參數(shù)校驗與全局異常處理的方法_第1頁
springboot整合JSR303參數(shù)校驗與全局異常處理的方法_第2頁
springboot整合JSR303參數(shù)校驗與全局異常處理的方法_第3頁
springboot整合JSR303參數(shù)校驗與全局異常處理的方法_第4頁
springboot整合JSR303參數(shù)校驗與全局異常處理的方法_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第springboot整合JSR303參數(shù)校驗與全局異常處理的方法目錄一、前言二、JSR303簡介三、導(dǎo)入依賴四、常用注解五、@Validated、@Valid區(qū)別六、常用使用測試1.實體類添加校驗2.統(tǒng)一返回類型3.測試類4.普通測試結(jié)果5.我們把異常返回給頁面6.異常處理結(jié)果七、抽離全局異常處理1.心得體會2.書寫ExceptionControllerAdvice3.測試結(jié)果八、分組校驗1.需求2.創(chuàng)建分組接口(不需寫任何內(nèi)容)3.在需要二義性的字段上添加分組4.不同Controller添加校驗規(guī)則5.測試九、自定義校驗1.定義自定義校驗器2.定義一個注解配合校驗器使用3.實體類添加一個新的校驗屬性4.測試十、總結(jié)

一、前言

我們在日常開發(fā)中,避不開的就是參數(shù)校驗,有人說前端不是會在表單中進(jìn)行校驗的嗎?在后端中,我們可以直接不管前端怎么樣判斷過濾,我們后端都需要進(jìn)行再次判斷,為了安全。因為前端很容易拜托,當(dāng)測試使用PostMan來測試,如果后端沒有校驗,不就亂了嗎?肯定會有很多異常的。今天小編和大家一起學(xué)習(xí)一下JSR303專門用于參數(shù)校驗的,算是一個工具吧!

二、JSR303簡介

JSR-303是JAVAEE6中的一項子規(guī)范,叫做BeanValidation,官方參考實現(xiàn)是HibernateValidator。

HibernateValidator提供了JSR303規(guī)范中所有內(nèi)置constraint的實現(xiàn),除此之外還有一些附加的constraint。

Hibernate官網(wǎng)

官網(wǎng)介紹:

驗證數(shù)據(jù)是一項常見任務(wù),它發(fā)生在從表示層到持久層的所有應(yīng)用程序?qū)又小MǔT诿恳粚佣紝崿F(xiàn)相同的驗證邏輯,這既耗時又容易出錯。為了避免重復(fù)這些驗證,開發(fā)人員經(jīng)常將驗證邏輯直接捆綁到域模型中,將域類與驗證代碼混在一起,而驗證代碼實際上是關(guān)于類本身的元數(shù)據(jù)。

JakartaBeanValidation2.0-為實體和方法驗證定義了元數(shù)據(jù)模型和API。默認(rèn)元數(shù)據(jù)源是注釋,能夠通過使用XML覆蓋和擴(kuò)展元數(shù)據(jù)。API不依賴于特定的應(yīng)用程序?qū)踊蚓幊棠P汀K貏e不依賴于Web或持久層,并且可用于服務(wù)器端應(yīng)用程序編程以及富客戶端Swing應(yīng)用程序開發(fā)人員。

三、導(dǎo)入依賴

dependency

groupIdorg.springframework.boot/groupId

artifactIdspring-boot-starter-validation/artifactId

/dependency

四、常用注解

約束注解名稱約束注解說明@Null用于驗證對象為null@NotNull用于對象不能為null,無法查檢長度為0的字符串@NotBlank只用于String類型上,不能為null且trim()之后的size0@NotEmpty用于集合類、String類不能為null,且size0。但是帶有空格的字符串校驗不出來@Size用于對象(Array,Collection,Map,String)長度是否在給定的范圍之內(nèi)@Length用于String對象的大小必須在指定的范圍內(nèi)@Pattern用于String對象是否符合正則表達(dá)式的規(guī)則@Email用于String對象是否符合郵箱格式@Min用于Number和String對象是否大等于指定的值@Max用于Number和String對象是否小等于指定的值@AssertTrue用于Boolean對象是否為true@AssertFalse用于Boolean對象是否為false

所有的大家參考jar包

五、@Validated、@Valid區(qū)別

@Validated:

Spring提供的支持分組校驗可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上由于無法加在成員屬性(字段)上,所以無法單獨完成級聯(lián)校驗,需要配合@Valid

@Valid:

JDK提供的(標(biāo)準(zhǔn)JSR-303規(guī)范)不支持分組校驗可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上可以加在成員屬性(字段)上,能夠獨自完成級聯(lián)校驗

總結(jié):@Validated用到分組時使用,一個學(xué)校對象里還有很多個學(xué)生對象需要使用@Validated在Controller方法參數(shù)前加上,@Valid加在學(xué)校中的學(xué)生屬性上,不加則無法對學(xué)生對象里的屬性進(jìn)行校驗!

區(qū)別參考博客地址

例子:

@Data

publicclassSchool{

@NotBlank

privateStringid;

privateStringname;

@Valid//需要加上,否則不會驗證student類中的校驗注解

@NotNull//且需要觸發(fā)該字段的驗證才會進(jìn)行嵌套驗證。

privateListStudentlist;

@Data

publicclassStudent{

@NotBlank

privateStringid;

privateStringname;

privateintage;

@PostMapping("/test")

publicResulttest(@Validated@RequestBodySchoolschool){

}

六、常用使用測試

1.實體類添加校驗

importlombok.Data;

importjavax.validation.constraints.Min;

importjavax.validation.constraints.NotBlank;

importjavax.validation.constraints.NotNull;

importjavax.validation.constraints.Pattern;

importjava.io.Serializable;

@Data

publicclassBrandEntityimplementsSerializable{

privatestaticfinallongserialVersionUID=1L;

*品牌id

@NotNull(message="修改必須有品牌id")

privateLongbrandId;

*品牌名F

@NotBlank(message="品牌名必須提交")

privateStringname;

*品牌logo地址

@NotBlank(message="地址必須不為空")

privateStringlogo;

*介紹

privateStringdescript;

*檢索首字母

//正則表達(dá)式

@Pattern(regexp="^[a-zA-Z]$",message="檢索的首字母必須是字母")

privateStringfirstLetter;

*排序

@Min(value=0,message="排序必須大于等于0")

privateIntegersort;

}

2.統(tǒng)一返回類型

importcom.alibaba.druid.util.StringUtils;

importio.swagger.annotations.ApiModel;

importio.swagger.annotations.ApiModelProperty;

importlombok.AllArgsConstructor;

importlombok.Data;

importlombok.NoArgsConstructor;

//統(tǒng)一返回結(jié)果

@Data

@NoArgsConstructor

@AllArgsConstructor

@ApiModel

publicclassResultT{

@ApiModelProperty("響應(yīng)碼")

privateIntegercode;

@ApiModelProperty("相應(yīng)信息")

privateStringmsg;

@ApiModelProperty("返回對象或者集合")

privateTdata;

//成功碼

publicstaticfinalIntegerSUCCESS_CODE=200;

//成功消息

publicstaticfinalStringSUCCESS_MSG="SUCCESS";

//失敗

publicstaticfinalIntegerERROR_CODE=201;

publicstaticfinalStringERROR_MSG="系統(tǒng)異常,請聯(lián)系管理員";

//沒有權(quán)限的響應(yīng)碼

publicstaticfinalIntegerNO_AUTH_COOD=999;

//執(zhí)行成功

publicstaticTResultTsuccess(Tdata){

returnnewResult(SUCCESS_CODE,SUCCESS_MSG,data);

//執(zhí)行失敗

publicstaticTResultfailed(Stringmsg){

msg=StringUtils.isEmpty(msg)ERROR_MSG:msg;

returnnewResult(ERROR_CODE,msg,"");

//傳入錯誤碼的方法

publicstaticTResultfailed(intcode,Stringmsg){

msg=StringUtils.isEmpty(msg)ERROR_MSG:msg;

returnnewResult(code,msg,"");

//傳入錯誤碼的數(shù)據(jù)

publicstaticTResultfailed(intcode,Stringmsg,Tdata){

msg=StringUtils.isEmpty(msg)ERROR_MSG:msg;

returnnewResult(code,msg,data);

}

3.測試類

@PostMapping("/add")

publicResultadd(@Valid@RequestBodyBrandEntitybrandEntity){

returnResult.success("成功");

}

遇到的坑:小編在公司的項目中添加沒什么問題,但是就是無法觸發(fā)校驗,看到的是Springboot版本太高了,所有要添加下面的依賴才觸發(fā)。

dependency

groupIdorg.hibernate.validator/groupId

artifactIdhibernate-validator/artifactId

version6.0.18.Final/version

/dependency

4.普通測試結(jié)果

5.我們把異常返回給頁面

@PostMapping("/add")

publicResultadd(@Valid@RequestBodyBrandEntitybrandEntity,BindingResultbindingResult){

if(bindingResult.hasErrors()){

MapString,Stringmap=newHashMap();

bindingResult.getFieldErrors().forEach(item-{

map.put(item.getField(),item.getDefaultMessage());

returnResult.failed(400,"提交的數(shù)據(jù)不合規(guī)范",map);

returnResult.success("成功");

}

6.異常處理結(jié)果

{

"code":400,

"data":{

"name":"品牌名必須提交",

"logo":"地址必須不為空"

"msg":"提交的數(shù)據(jù)不合規(guī)范"

}

七、抽離全局異常處理

1.心得體會

上面我們要在每個校驗的接口上面寫,所以我們要抽離出來做個全局異常。并且要改進(jìn)一下,原來的是把錯誤信息放到data里,但是正常情況下的data是返回給前端的數(shù)據(jù)。我們這樣把異常數(shù)據(jù)放進(jìn)去,會使data的數(shù)據(jù)有二義性。這樣對于前端就不知道里面是數(shù)據(jù)還是報錯信息了哈,這樣就可以直接前端展示msg里面的提示即可!

2.書寫ExceptionControllerAdvice

importcom.wang.test.demo.response.Result;

importlombok.extern.slf4j.Slf4j;

importorg.springframework.validation.BindingResult;

importorg.springframework.web.bind.MethodArgumentNotValidException;

importorg.springframework.web.bind.annotation.ExceptionHandler;

importorg.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j

@RestControllerAdvice(basePackages="com.wang.test.demo.controller")

publicclassExceptionControllerAdvice{

@ExceptionHandler(value=MethodArgumentNotValidException.class)

publicResulthandleVaildException(MethodArgumentNotValidExceptione){

log.error("數(shù)據(jù)校驗出現(xiàn)問題:{},異常類型:{}",e.getMessage(),e.getClass());

BindingResultbindingResult=e.getBindingResult();

StringBufferstringBuffer=newStringBuffer();

bindingResult.getFieldErrors().forEach(item-{

//獲取錯誤信息

Stringmessage=item.getDefaultMessage();

//獲取錯誤的屬性名字

Stringfield=item.getField();

stringBuffer.append(field+":"+message+"");

returnResult.failed(400,stringBuffer+"");

@ExceptionHandler(value=Throwable.class)

publicResulthandleException(Throwablethrowable){

log.error("錯誤",throwable);

returnResult.failed(400,"系統(tǒng)異常");

3.測試結(jié)果

{

code:400,

data:,

msg:logo:地址必須不為空name:品牌名必須提交

}

八、分組校驗

1.需求

我們在做校驗的時候,通常會遇到一個實體類的添加和修改,他們的校驗規(guī)則是不同的,所以分組顯得尤為重要。他可以幫助我們少建一個冗余的實體類,所以我們必須要會的。

2.創(chuàng)建分組接口(不需寫任何內(nèi)容)

publicinterfaceEditGroup{

publicinterfaceAddGroup{

}

3.在需要二義性的字段上添加分組

/**

*品牌id

@NotNull(message="修改必須有品牌id",groups={EditGroup.class})

@Null(message="新增不能指定id",groups={AddGroup.class})

privateLongbrandId;

//其余屬性我們不變

4.不同Controller添加校驗規(guī)則

注意:我們要進(jìn)行分組,所以@Valid不能使用了,要使用@Validated。相信大家已經(jīng)看到上面的他倆區(qū)別了哈!

@PostMapping("/add")

publicResultadd(@Validated({AddGroup.class})@RequestBodyBrandEntitybrandEntity){

returnResult.success("成功");

@PostMapping("/edit")

publicResultedit(@Validated({EditGroup.class})@RequestBodyBrandEntitybrandEntity){

returnResult.success("成功");

}

5.測試

九、自定義校驗

1.定義自定義校驗器

importjavax.validation.ConstraintValidator;

importjavax.validation.ConstraintValidatorContext;

importjava.util.HashSet;

importjava.util.Set;

//編寫自定義的校驗器

publicclassListValueConstraintValidatorimplementsConstraintValidatorListValue,Integer{

privateSetIntegerset=newHashSetInteger

//初始化方法

@Override

publicvoidinitialize(ListValueconstraintAnnotation){

int[]value=constraintAnnotation.vals();

for(inti:value){

set.add(i);

*判斷是否校驗成功

*@paramvalue需要校驗的值

*@paramcontext

*@return

@Override

publicboole

溫馨提示

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

評論

0/150

提交評論