一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring Boot參數校驗及分組校驗的使用教程

Spring Boot參數校驗及分組校驗的使用教程

2021-11-12 14:49江巖 Java教程

在日常的開發中,參數校驗是非常重要的一個環節,嚴格參數校驗會減少很多出bug的概率,增加接口的安全性,下面這篇文章主要給大家介紹了關于Spring Boot參數校驗及分組校驗使用的相關資料,需要的朋友可以參考下

一  前言

做web開發有一點很煩人就是要對前端輸入參數進行校驗,基本上每個接口都要對參數進行校驗,比如一些非空校驗、格式校驗等。如果參數比較少的話還是容易處理的一但參數比較多了的話代碼中就會出現大量的if-else語句。

使用這種方式雖然簡單直接,但是也有不好的地方,一是降低了開發效率,因為我們需要校驗的參數會存在很多地方,并且不同地方會有重復校驗,其次降低了代碼可讀性,因為在業務代碼中摻雜了太多額外工作的代碼。

所以我們可以使用validator組件來代替我們進行不必要的coding操作。本文基于validator的介紹資料,也結合自己在項目中的實際使用經驗進行了總結,希望能幫到大家。

1  什么是validator

Bean Validation是Java定義的一套基于注解的數據校驗規范,目前已經從JSR 303的1.0版本升級到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成于2017.08),已經經歷了三個版本 。需要注意的是,JSR只是一項標準,它規定了一些校驗注解的規范,但沒有實現,比如@Null、@NotNull、@Pattern等,它們位于 javax.validation.constraints這個包下。而hibernate validator是對這個規范的實現,并增加了一些其他校驗注解,如 @NotBlank、@NotEmpty、@Length等,它們位于org.hibernate.validator.constraints這個包下。

如果我們的項目使用了Spring Boot,hibernate validator框架已經集成在 spring-boot-starter-web中,所以無需再添加其他依賴。如果不是Spring Boot項目,需要添加如下依賴。

?
1
2
3
4
5
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.8.Final</version>
</dependency>

二  注解介紹

1  validator內置注解

 

注解 說明
@Null 被注釋的元素必須為null
@NotNull 被注釋的元素不能為null
@AssertTrue 被注釋的元素必須為true
@AssertFalse 被注釋的元素必須為false
@Min(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
@Max(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
@DecimalMin(value) 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值
@DecimalMax(value) 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值
@Size(max,min) 被注釋的元素的大小必須在指定的范圍內
@Digits(integer, fraction) 被注釋的元素必須是一個數字,其值必須必須在可接受的范圍內
@Past 被注釋的元素必須是一個過去的日期
@Future 被注釋的元素必須是一個將來的日期
@Pattern(value) 被注釋的元素必須符合指定的正則表達式

 

hibernate validator中擴展定義了如下注解:

 

注解 說明
@NotBlank 被注釋的元素不能為null,且長度必須大于0,只能用于注解字符串
@Email 被注釋的元素必須是電子郵箱地址
@Length(min=,max=) 被注釋的字符串的大小必須在指定的范圍內
@NotEmpty 被注釋的元素值不為null且不為空,支持字符串、集合、Map和數組類型
@Range 被注釋的元素必須在規定的范圍內

 

三  使用

使用起來比較簡單,都是使用注解方式使用。具體來說分為單參數校驗、對象參數校驗,單參數校驗就是controller接口按照單參數接收前端傳值,沒有封裝對象進行接收,如果有封裝對象那就是對象參數校驗。

1  單參數校驗

單參數校驗只需要在參數前添加注解即可,如下所示:

?
1
2
3
public Result deleteUser(@NotNull(message = "id不能為空") Long id) {
  // do something
}

但有一點需要注意,如果使用單參數校驗,controller類上必須添加@Validated注解,如下所示:

?
1
2
3
4
5
6
@RestController
@RequestMapping("/user")
@Validated // 單參數校驗需要加的注解
public class UserController {
  // do something
}

2  對象參數校驗

對象參數校驗使用時,需要先在對象的校驗屬性上添加注解,然后在Controller方法的對象參數前添加@Validated 注解,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public Result addUser(@Validated UserAO userAo) {
    // do something
}
 
public class UserAO {
  @NotBlank
  private String name;
 
  @NotNull
  private Integer age;
  
  ……
}

注解分組

在對象參數校驗場景下,有一種特殊場景,同一個參數對象在不同的場景下有不同的校驗規則。比如,在創建對象時不需要傳入id字段(id字段是主鍵,由系統生成,不由用戶指定),但是在修改對象時就必須要傳入id字段。在這樣的場景下就需要對注解進行分組。

1)組件有個默認分組Default.class, 所以我們可以再創建一個分組UpdateAction.class,如下所示:

?
1
2
public interface UpdateAction {
}

2)在參數類中需要校驗的屬性上,在注解中添加groups屬性:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class UserAO {
 
    @NotNull(groups = UpdateAction.class, message = "id不能為空")
    private Long id;
    
    @NotBlank
    private String name;
 
    @NotNull
    private Integer age;
    
    ……
}

如上所示,就表示只在UpdateAction分組下校驗id字段,在默認情況下就會校驗name字段和age字段。

然后在controller的方法中,在@Validated注解里指定哪種場景即可,沒有指定就代表采用Default.class,采用其他分組就需要顯示指定。如下代碼便表示在addUser()接口中按照默認情況進行參數校驗,在updateUser()接口中按照默認情況和UpdateAction分組對參數進行共同校驗。

?
1
2
3
public Result addUser(@Validated UserAO userAo) {
  // do something
}
?
1
2
3
public Result updateUser(@Validated({Default.class, UpdateAction.class}) UserAO userAo) {
  // do something
}

對象嵌套

如果需要校驗的參數對象中還嵌套有一個對象屬性,而該嵌套的對象屬性也需要校驗,那么就需要在該對象屬性上增加@Valid注解。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class UserAO {
 
    @NotNull(groups = UpdateAction.class, message = "id不能為空")
    private Long id;
    
    @NotBlank
    private String name;
 
    @NotNull
    private Integer age;
    
    @Valid
    private Phone phone;
    
    ……
}
 
public class Phone {
    @NotBlank
    private String operatorType;
    
    @NotBlank
    private String phoneNum;
}

3  錯誤消息的捕獲

參數校驗失敗后會拋出異常,我們只需要在全局異常處理類中捕獲參數校驗的失敗異常,然后將錯誤消息添加到返回值中即可。捕獲異常的方法如下所示,返回值Result是我們系統自定義的返回值類。

?
1
2
3
4
5
6
7
8
@RestControllerAdvice(basePackages= {"com.alibaba.dc.controller","com.alibaba.dc.service"})
public class GlobalExceptionHandler {
 
  @ExceptionHandler(value = {Throwable.class})
  Result handleException(Throwable e, HttpServletRequest request){
    // 異常處理
        }
}

需要注意的是,如果缺少參數拋出的異常是MissingServletRequestParameterException,單參數校驗失敗后拋出的異常是ConstraintViolationException,get請求的對象參數校驗失敗后拋出的異常是BindException,post請求的對象參數校驗失敗后拋出的異常是MethodArgumentNotValidException,不同異常對象的結構不同,對異常消息的提取方式也就不同。如下圖所示:

1)MissingServletRequestParameterException

?
1
2
3
4
5
6
if(e instanceof MissingServletRequestParameterException){
    Result result = Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);
    String msg = MessageFormat.format("缺少參數{0}", ((MissingServletRequestParameterException) e).getParameterName());
    result.setMessage(msg);
    return result;
}

2)ConstraintViolationException異常

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(e instanceof ConstraintViolationException){
  // 單個參數校驗異常
  Result result = Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);
  Set<ConstraintViolation<?>> sets = ((ConstraintViolationException) e).getConstraintViolations();
  if(CollectionUtils.isNotEmpty(sets)){
    StringBuilder sb = new StringBuilder();
    sets.forEach(error -> {
                    if (error instanceof FieldError) {
                        sb.append(((FieldError)error).getField()).append(":");
                    }
                    sb.append(error.getMessage()).append(";");
                });
    String msg = sb.toString();
    msg = StringUtils.substring(msg, 0, msg.length() -1);
    result.setMessage(msg);
  }
  return result;
}

3)BindException異常

?
1
2
3
4
5
6
7
8
9
10
if (e instanceof BindException){
      // get請求的對象參數校驗異常
      Result result = Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);
      List<ObjectError> errors = ((BindException) e).getBindingResult().getAllErrors();
      String msg = getValidExceptionMsg(errors);
      if (StringUtils.isNotBlank(msg)){
        result.setMessage(msg);
      }
      return result;
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private String getValidExceptionMsg(List<ObjectError> errors) {
  if(CollectionUtils.isNotEmpty(errors)){
    StringBuilder sb = new StringBuilder();
    errors.forEach(error -> {
                    if (error instanceof FieldError) {
                       sb.append(((FieldError)error).getField()).append(":");
                    }
                    sb.append(error.getDefaultMessage()).append(";");
                });
    String msg = sb.toString();
    msg = StringUtils.substring(msg, 0, msg.length() -1);
    return msg;
  }
  return null;
}

4)MethodArgumentNotValidException異常

?
1
2
3
4
5
6
7
8
9
10
if (e instanceof MethodArgumentNotValidException){
      // post請求的對象參數校驗異常
      Result result = Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);
      List<ObjectError> errors = ((MethodArgumentNotValidException) e).getBindingResult().getAllErrors();
      String msg = getValidExceptionMsg(errors);
      if (StringUtils.isNotBlank(msg)){
        result.setMessage(msg);
      }
      return result;
}

總結

到此這篇關于Spring Boot參數校驗及分組校驗使用的文章就介紹到這了,更多相關SpringBoot參數校驗及分組校驗內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://mp.weixin.qq.com/s/x6_mNdtb6i2XmTiyz4kXrg

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
主站蜘蛛池模板: 日本黄色大片网站 | 男人的天堂视频 | 99久热只有精品视频免费看 | 国产视频一区在线观看 | 欧美日韩在线观看区一二 | 国产亚洲高清国产拍精品 | 国产精品久久久久无毒 | www.色.con| 国产欧美亚洲精品第一页青草 | 国产射频放大器 | 日韩精品高清自在线 | www.色姐姐| freefron性中国国产高清 | 性派对videos18party | 青青青久热国产精品视频 | 国产激情一区二区三区成人91 | 亚洲国产精品自在在线观看 | 日本一区二区三区四区无限 | t66y地址一地址二地址三 | 果冻传媒在线视频观看免费 | 亚洲gogo人体大胆西西安徽 | 免费观看日本视频 | 美女鸡| 91免费在线 | 99久久国语露脸精品国产 | 北岛玲在线播放 | 国产精品亚洲精品日韩已满 | 精品福利视频一区二区三区 | 国产一级持黄大片99久久 | 男男18视频免费网站 | 日本高清视频在线观看 | 2022国产麻豆剧传媒剧情 | 欧美日韩国产成人综合在线 | 麻麻与子乱肉小说怀孕 | 国产日韩一区二区 | 天天综合天天综合色在线 | 国产专区视频在线观看 | 免费看黄色片的网站 | 97理伦| 亚洲高清中文字幕精品不卡 | 午夜影院0606 |