實習筆記---springboot的參數校驗

前言

以後的知識點呀、報錯修復啥的都改成實習筆記啦,除非我實習期結束啦。這幾天鑑權部分基本完成了,老闆讓我寫CRUD,秉承着代碼優雅的前提,我開始看參數校驗。

整齊但是不優雅的if-else

你在日常敲代碼中,有沒有遇到這種情況,前端傳到後端的參數多,且大多數都需要校驗,這樣子你是不是需要很多if來判斷他們是否是符合邏輯的。比如:

if(schoolInfo!=null&&schoolInfo.getId()!=null) {
            return RestResult.failure();
        }

以上舉個小例子,這樣子寫雖然看起來很整齊且易懂,但是參數一多,邏輯還沒開始,就一堆if語句在上面,有點不太優雅。

@Validated

其實springboot官方文檔裏有推薦使用這個東西來做參數校驗,用法也很簡單,有興趣的小夥伴可以去網上搜索下用法,這裏舉個例子

@Null

表示參數必須爲空,只需要在實體類的參數上標識即可,您還可以加上報錯信息,例如:

@Null(message = "Id存在非法值")
private String id;

標識後,在接收參數的controller上,使用@Validated註解,例如

public RestResult addSchool(@Validated SchoolInfo schoolInfo)

如此,如果id中有值,會報異常,異常錯誤信息是你在message中填寫的字。

不太好看的返回

如果您將錯誤信息直接返回的話,會是一大串字符串,這裏測試的時候忘記截圖了,小夥伴可以自己看看,爲了使返回好看一點,有請今天的第二個主角:

@ControllerAdvice 統一異常處理

首先,我們要知道,在不同情況下,@Validated 返回的異常是不同的,以下:

//處理Get請求中 使用@Valid 驗證路徑中請求實體校驗失敗後拋出的異常,詳情繼續往下看代碼
BindException e
//處理請求參數格式錯誤 @RequestParam上validate失敗後拋出的異常是
ConstraintViolationException e
//處理請求參數格式錯誤 @RequestBody上validate失敗後拋出的異常是MethodArgumentNotValidException異常。
MethodArgumentNotValidException e

當我們知道這些之後,就可以開始寫異常處理:

/**
 * 統一異常處理
 * jackson
 * 時間:2020年04月10日16:03:05
 */

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

	@ExceptionHandler(Exception.class)
	public RestResult handle(Throwable e,  HttpServletRequest request)  {

		/**
		 * 參數校驗
		 */
		if(e instanceof BindException)
			return this.BindExceptionHandler((BindException) e);
		if(e instanceof ConstraintViolationException)
			return this.ConstraintViolationExceptionHandler((ConstraintViolationException) e);
		if(e instanceof MethodArgumentNotValidException)
			return this.MethodArgumentNotValidExceptionHandler((MethodArgumentNotValidException) e);
			
	}
	
	//處理Get請求中 使用@Valid 驗證路徑中請求實體校驗失敗後拋出的異常,詳情繼續往下看代碼
	public RestResult  BindExceptionHandler(BindException e) {
		log.error("參數異常");
		String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}

	//處理請求參數格式錯誤 @RequestParam上validate失敗後拋出的異常是javax.validation.ConstraintViolationException
	public RestResult ConstraintViolationExceptionHandler(ConstraintViolationException e) {
		log.error("參數異常");
		String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}

	//處理請求參數格式錯誤 @RequestBody上validate失敗後拋出的異常是MethodArgumentNotValidException異常。
	public RestResult MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
		log.error("參數異常");
		String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
		return RestResult.failure(message);
	}
}

如果對統一異常管理不瞭解的小夥伴,建議去別人的博客觀摩觀摩,這裏controller一旦拋出異常,會被@RestControllerAdvice捕獲到,進入邏輯判斷,這裏比對了三個不同的異常,進行不同的處理。
爲了方便小夥伴,我貼下我的返回類

/**
 * Description: 返回結果對象
 * Author:  jackson
 * Date: 2020年04月10日10:16:46
 **/

@Data
public class RestResult<T> implements Serializable {

    private String msg;

    private Integer code;

    private T data;

    Long count;//數據數量

    List<T> datas;//返回數據

    public RestResult(Integer code, String msg) {
        super();
        this.code = code;
        this.msg = msg;
    }

    public RestResult(Integer code, String msg,T data) {
        super();
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public RestResult(Integer code, String msg, List<T> datas, Long count) {
        this.code = code;
        this.msg = msg;
        this.datas = datas;
        this.count = count;
    }


    /* 無數據傳輸的 成功返回 */
    public static <T> RestResult<T> success() {
        return new RestResult<T>( ErrorCode.SUCCESS.getErrorCode(),  ErrorCode.SUCCESS.getErrorMsg());
    }

//    public static <T> RestResult<T> success(String msg) {
//        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(), msg);
//    }

    public static <T> RestResult<T> success(ErrorCode errorCode) {
        return new RestResult<T>( errorCode.getErrorCode(),  errorCode.getErrorMsg());
    }

    /* 單個數據傳輸的 成功返回 */
    public static <T> RestResult<T> success(T data) {
        return new RestResult<T>( ErrorCode.SUCCESS.getErrorCode(),  ErrorCode.SUCCESS.getErrorMsg(), data);
    }

    public static <T> RestResult<T> success(String msg, T data) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(), msg, data);
    }

    public static <T> RestResult<T> success(ErrorCode errorCode, T data) {
        return new RestResult<T>( errorCode.getErrorCode(),  errorCode.getErrorMsg(), data);
    }

    /* 分頁數據傳輸的 成功返回 */
    public static <T> RestResult<T> success(Long count, List<T> datas) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(),ErrorCode.SUCCESS.getErrorMsg(),datas,count);
    }

    public static <T> RestResult<T> success(String msg, Long count, List<T> datas) {
        return new RestResult<T>(ErrorCode.SUCCESS.getErrorCode(), msg, datas, count);
    }

    public static <T> RestResult<T> success(ErrorCode resultCode, Long count, List<T> datas) {
        return new RestResult<T>( resultCode.getErrorCode(),  resultCode.getErrorMsg(), datas ,count);
    }

    /* 無數據傳輸的 失敗返回 */
    public static <T> RestResult<T> failure(String message) {
        return new RestResult<T>( ErrorCode.FAILED.getErrorCode(), message);
    }

    public static <T> RestResult<T> failure() {
        return new RestResult<T>( ErrorCode.FAILED.getErrorCode(), ErrorCode.FAILED.getErrorMsg());
    }

    public static <T> RestResult<T> failure(ErrorCode resultCode) {
        return new RestResult<T>( resultCode.getErrorCode(),  resultCode.getErrorMsg());
    }

    public static <T> RestResult<T> failure(CustomizeException c) {
        return new RestResult<T>( c.getCode(),c.getMessage());
    }


    public static <T> RestResult<T> failure(Integer code, String msg) {
        return new RestResult<T>( code,  msg);
    }

}

哎喲,還是覺得自己的異常捕獲類寫的不太好,不知道有沒有大佬指正下。

以上,希望能幫助到小夥伴。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章