測試開發專題:spring-boot自定義返回參數校驗錯誤信息

以前兩篇文章 Spring-boot自定義參數校驗註解如何在spring-boot中進行參數校驗,咱們介紹了,參數校驗以及如何自定義參數校驗註解,可是當傳遞參數出錯時,只是把錯誤信息打印到了控制檯,合理的作法是應該把校驗的錯誤信息返回給前端,告知用戶那裏有問題,下面就這一步內容進行說明。html

請求body參數

上篇文章 Spring-boot自定義參數校驗註解的最後,在控制檯打印了校驗出錯的信息前端

出錯的異常類是MethodArgumentNotValidException,那若是想要自定義異常的返回,就須要在全局的異常處理器中針對這種異常進行處理。java

在這篇文章 spring-boot自定義異常返回中,咱們說了如何進行自定義異常的返回,參數校驗的錯誤信息返回依然按照此方式進行處理,在全局異常處理類中定義異常處理方法:spring

@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public UnifyResponse handlerBeanValidationException(HttpServletRequest request,
                                                    MethodArgumentNotValidException ex) {
    String requestUri = request.getRequestURI();
    String method = request.getMethod();

    List<ObjectError> errors = ex.getBindingResult().getAllErrors();
    return UnifyResponse.builder()
            .code(5000)
            .message(formatError(errors))
            .requestUri(method + " " + requestUri)
            .build();
}

private String formatError(List<ObjectError> errors) {
    StringBuilder builder = new StringBuilder();
    errors.forEach(error -> builder.append(error.getDefaultMessage()).append(";"));
    return builder.toString();
}

咱們來對上面的代碼進行一下解釋:app

  • 由於這個處理方法只是針對MethodArgumentNotValidException這個異常進行處理,因此@ExceptionHandler(value = MethodArgumentNotValidException.class)這裏指定
  • @ResponseStatus(HttpStatus.BAD_REQUEST),全部的參數校驗錯誤都是一類的,狀態碼設置爲HttpStatus.BAD_REQUEST,也就是code等於400,固然也能夠定義爲其餘的,按照本身業務需求定義就好,能夠參考這篇文章 spring-boot自定義異常返回裏關於自定義狀態碼的部分。
  • @ResponseBody,由於這個異常處理方法要返回自定義的對象,因此要使用這個註解,否則spring-boot是不會對自定義對象進行序列化的
  • List<ObjectError> errors = ex.getBindingResult().getAllErrors()進行參數校驗的時候,可能多個參數都有問題,咱們但願可以有問題的參數的錯誤信息所有都返回回去,因此這裏要獲取全部的錯誤。

回顧一下參數的定義,對這裏有疑惑的同窗能夠看一下這篇文章Spring-boot自定義參數校驗註解函數

@Builder
@Getter
@Setter
@PasswordEqual(min = 5, message = "密碼和確認密碼不同")
public class UserDto {

    private int userId;

    @Length(min = 2, max = 10, message = "用戶名長度必須在2-10的範圍內")
    private String username;

    private String password;

    private String confirmPassword;
}

接下來咱們定再定義一個簡單的接口,當傳參出錯時看異常處理方法可否按照定義的那樣返回錯誤信息spring-boot

@RequestMapping("/v2/user/create")
public UserDto createUser(@RequestBody @Validated  UserDto userDto){
    return userDto;
}

咱們先來構造一個密碼和確認密碼不一致的狀況測試

file

能夠看到定義的錯誤信息被返回,並且狀態碼和自定義的code都是符合設計的,接下來咱們再看一下多個參數錯誤的場景:ui

file

上面的場景中,用戶名是不符合要求的,密碼和確認密碼也不同,因此會產生兩條錯誤信息,將其拼接到一塊兒,返回給前端。設計

以前討論的都是body裏提交的參數,接下來咱們看下路徑參數或者查詢參數校驗出錯時的處理

查詢參數和路徑參數

咱們先定義兩個接口一個是路徑參數查詢信息,一個是經過查詢參數查詢信息

@GetMapping("/v2/user/info")
public UserDto getUserInfo(@RequestParam @Length(min = 2, max = 5, message = "用戶名長度必須在2-5的範圍")
                                       String username){
    return UserDto.builder()
            .userId(1000)
            .username(username)
            .build();
}

@GetMapping("/v2/user/{username}")
public UserDto getUserInfoV2(@PathVariable @Length(min = 2, max = 5, message = "用戶名長度必須在2-5的範圍") String username){
    return UserDto.builder()
            .userId(2000)
            .username(username)
            .build();
}

而後咱們訪問這兩接口,當發生錯誤時,看看他們會不會進入上文定義的異常處理方法中:

file

很明顯,並無進入上文定義的異常處理方法中,而是進入了handleException這個異常方法當中,這個算是個兜底的異常處理方法。

看一下控制檯的輸出:

file

這裏拋出了ConstraintViolationException異常,這個異常咱們並無定製對應的異常處理函數,下面咱們就來寫一下:

@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public UnifyResponse handlerConstraintViolationException(HttpServletRequest request, ConstraintViolationException ex){
    String requestUri = request.getRequestURI();
    String method = request.getMethod();

    Set<ConstraintViolation<?>> errors = ex.getConstraintViolations();
    return UnifyResponse.builder()
            .code(6000)
            .message(formatConstraintException(errors))
            .requestUri(method + " " + requestUri)
            .build();
}

private String formatConstraintException(Set<ConstraintViolation<?>> constraintViolations){
    StringBuilder builder = new StringBuilder();
    constraintViolations.forEach(constraintViolation -> builder.append(constraintViolation.getMessage()));
    return builder.toString();
}

總體來講異常處理和上文幾乎是同樣的,只是獲取錯誤message的方式不同而已,咱們再請求一下:

file

至此參數校驗的錯誤message自定義返回,都完成了。

本文連接:https://www.immortalp.com/articles/2020/05/16/1589623786527.html
歡迎你們去 個人博客 瞅瞅,裏面有更多關於測試實戰的內容哦!!

相關文章
相關標籤/搜索