欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring Boot參數(shù)校驗及分組校驗的使用教程

 更新時間:2021年08月10日 15:14:22   作者:江巖  
在日常的開發(fā)中,參數(shù)校驗是非常重要的一個環(huán)節(jié),嚴格參數(shù)校驗會減少很多出bug的概率,增加接口的安全性,下面這篇文章主要給大家介紹了關(guān)于Spring Boot參數(shù)校驗及分組校驗使用的相關(guān)資料,需要的朋友可以參考下

一  前言

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

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

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

1  什么是validator

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

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

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.8.Final</version>
</dependency>

二  注解介紹

1  validator內(nèi)置注解

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

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

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

三  使用

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

1  單參數(shù)校驗

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

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

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

@RestController
@RequestMapping("/user")
@Validated // 單參數(shù)校驗需要加的注解
public class UserController {
  // do something
}

2  對象參數(shù)校驗

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

public Result addUser(@Validated UserAO userAo) {
    // do something
}

public class UserAO {
  @NotBlank
  private String name;

  @NotNull
  private Integer age;
  
  ……
}

注解分組

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

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

public interface UpdateAction {
}

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

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()接口中按照默認情況進行參數(shù)校驗,在updateUser()接口中按照默認情況和UpdateAction分組對參數(shù)進行共同校驗。

public Result addUser(@Validated UserAO userAo) {
  // do something
}

public Result updateUser(@Validated({Default.class, UpdateAction.class}) UserAO userAo) {
  // do something
}

對象嵌套

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

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  錯誤消息的捕獲

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

@RestControllerAdvice(basePackages= {"com.alibaba.dc.controller","com.alibaba.dc.service"})
public class GlobalExceptionHandler {

  @ExceptionHandler(value = {Throwable.class})
  Result handleException(Throwable e, HttpServletRequest request){
    // 異常處理
        }
}

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

1)MissingServletRequestParameterException

if(e instanceof MissingServletRequestParameterException){
    Result result = Result.buildErrorResult(ErrorCodeEnum.PARAM_ILLEGAL);
    String msg = MessageFormat.format("缺少參數(shù){0}", ((MissingServletRequestParameterException) e).getParameterName());
    result.setMessage(msg);
    return result;
}

2)ConstraintViolationException異常

if(e instanceof ConstraintViolationException){
  // 單個參數(shù)校驗異常
  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異常

if (e instanceof BindException){
      // get請求的對象參數(shù)校驗異常
      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;
}

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異常

if (e instanceof MethodArgumentNotValidException){
      // post請求的對象參數(shù)校驗異常
      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;
}

總結(jié)

到此這篇關(guān)于Spring Boot參數(shù)校驗及分組校驗使用的文章就介紹到這了,更多相關(guān)SpringBoot參數(shù)校驗及分組校驗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入淺析SpringBoot中的自動裝配

    深入淺析SpringBoot中的自動裝配

    SpringBoot的自動裝配是拆箱即用的基礎(chǔ),也是微服務(wù)化的前提。接下來通過本文給大家介紹SpringBoot中的自動裝配,感興趣的朋友跟隨腳本之家小編一起學(xué)習(xí)吧
    2018-05-05
  • 如何在 Java 中實現(xiàn)一個 redis 緩存服務(wù)

    如何在 Java 中實現(xiàn)一個 redis 緩存服務(wù)

    為什么要使用緩存?說到底是為了提高系統(tǒng)的運行速度。將用戶頻繁訪問的內(nèi)容存放在離用戶最近,訪問速度最快的地方,提高用戶的響應(yīng)速度。下面我們來一起深入學(xué)習(xí)一下吧
    2019-06-06
  • SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn)代碼

    SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn)代碼

    這篇文章主要介紹了SpringBoot整合WebSocket的客戶端和服務(wù)端的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • Java聊天室之使用Socket實現(xiàn)通信功能

    Java聊天室之使用Socket實現(xiàn)通信功能

    這篇文章主要為大家詳細介紹了Java簡易聊天室之使用Socket實現(xiàn)通信功能,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以了解一下
    2022-10-10
  • Feign如何實現(xiàn)第三方的HTTP請求

    Feign如何實現(xiàn)第三方的HTTP請求

    這篇文章主要介紹了Feign如何實現(xiàn)第三方的HTTP請求,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java爬蟲范例之使用Htmlunit爬取學(xué)校教務(wù)網(wǎng)課程表信息

    Java爬蟲范例之使用Htmlunit爬取學(xué)校教務(wù)網(wǎng)課程表信息

    htmlunit 是一款開源的java 頁面分析工具,讀取頁面后,可以有效的使用htmlunit分析頁面上的內(nèi)容。項目可以模擬瀏覽器運行,被譽為java瀏覽器的開源實現(xiàn)。今天我們用這款分析工具來爬取學(xué)校教務(wù)網(wǎng)課程表信息
    2021-11-11
  • Jmeter如何將每次測試的結(jié)果保存到文件中

    Jmeter如何將每次測試的結(jié)果保存到文件中

    這篇文章主要介紹了Jmeter如何將每次測試的結(jié)果保存到文件中的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java初學(xué)者常問的問題(推薦)

    Java初學(xué)者常問的問題(推薦)

    本文介紹一些Java初學(xué)者常問的問題,很多朋友對可以用%除以一個小數(shù)嗎? a += b 和 a = a + b 的效果有區(qū)別嗎? 聲明一個數(shù)組為什么需要花費大量時間? 為什么Java庫不用隨機pivot方式的快速排序?等等一系列問題有疑惑,下面就通過本文給大家詳細介紹下
    2017-03-03
  • Java自定義線程池的實現(xiàn)示例

    Java自定義線程池的實現(xiàn)示例

    本文主要介紹了Java自定義線程池的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java如何將Object數(shù)組轉(zhuǎn)換為指定類型數(shù)組

    java如何將Object數(shù)組轉(zhuǎn)換為指定類型數(shù)組

    這篇文章主要介紹了java如何將Object數(shù)組轉(zhuǎn)換為指定類型數(shù)組,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論