Spring-Validation(後端數據校驗) 你值得擁有

前言

最近看到不少童鞋在項目中的對請求參數的校驗都用的if來判斷各參數的屬性,如:java

if(StringUtils.isBlank(username)){
    return RR.exception("帳號不能爲空");
}

if(StringUtils.isBlank(password)){
    return RR.exception("密碼不能爲空");
}

if(StringUtils.isBlank(realName)){
    return RR.exception("姓名不能爲空");
}
......

每一個參數都須要這樣一個個去校驗null,返回對應信息,代碼就像疊羅漢同樣~~,在此,樓主強烈推薦一個神器:Validation,有了它,不再用這樣去校驗參數啦,可讓咱們在項目中不用太關注其餘東西,專一於業務邏輯的編寫。git

 

引入核心依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

 

使用示例-添加用戶

須要校驗的實體類,在此使用了一些經常使用的校驗註解,基本上可以見名知意,每一個註解中都有message屬性,就是校驗不經過後的提示信息web

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "Account", description = "用戶實體類")
public class Account implements Serializable {

    private static final long serialVersionUID = -6310331730721778951L;
    
    private Long id;

    @NotBlank(message = "用戶名不能爲空")
    @Length(max = 10, message = "用戶名最長爲10位")
    private String name;

    @Pattern(regexp = PatternUtil.PASSWORDREGEX, message = "密碼爲6-20位數字加字母組合")
    private String pwd;

    @NotBlank(message = "姓名不能爲空")
    @Length(max = 8, message = "姓名最長爲8位")
    private String realName;

    @Pattern(regexp = PatternUtil.PHONENOREGEX, message = "手機號碼格式不正確")
    private String phone;

    @NotNull(message = "用戶性別不能爲空")
    @Max(value = 1,message = "性別 0:男 1:女")
    @Min(value = 0,message = "性別 0:男 1:女")
    private Integer sex;
    
    @NotNull(message = "用戶狀態不能爲空")
    @Max(value = 1,message = "用戶狀態 0:啓用 1:禁用")
    @Min(value = 0,message = "用戶狀態 0:啓用 1:禁用")
    private Integer status;

    @Length(max = 200, message = "備註最長爲200個字符")
    private String rmk;
}

 

controller接口,注意在接收參數前需加上@Validated註解,這樣就會逐個去校驗實體類中須要加了校驗註解的的屬性,徹底經過才進入下一步業務處理,不然拋出MethodArgumentNotValidException異常,在這裏咱們直接將異常拋出,交給全局異常處理類來處理。正則表達式

@SysLog(menu = "用戶管理", function = "添加",filterParams = {"pwd","password","salt"})
@PermissionCheck("account:manager:add")
@PostMapping(value = "/add", produces = BaseConsts.REQUEST_HEADERS_CONTENT_TYPE)
@ApiOperation(value = "用戶管理-添加用戶接口", notes = "用戶管理-添加用戶接口", httpMethod = BaseConsts.REQUEST_METHOD, response = RR.class)
public RR add(@Validated @RequestBody Account account) throws Exception {
    return RR.success("添加用戶成功");
}

 

聲明全局異常處理類,處理全部異常,能夠隨業務須要將異常種類細分,返回錯誤碼,返回提示信息可自由定義...   這裏只需關注MethodArgumentNotValidException異常。spring

@RestControllerAdvice
public class GlobalExceptionHandle {

    /**
     * @param e
     * @return
     * @Description 未知異常處理
     */
    @ExceptionHandler(Exception.class)
    public RR handleException(Exception e) {
        e.printStackTrace();
        return RR.exception("系統異常,請聯繫管理員");
    }
    

    /**
     * @param e
     * @return
     * @Description 請求參數異常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public RR handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        return RR.exception("請求參數錯誤:[" + e.getBindingResult().getFieldError().getDefaultMessage() + "]");
    }
    

    /**
     * @param e
     * @return
     * @Description 系統業務服務異常
     */
    @ExceptionHandler(ServerException.class)
    public RR handleServerException(ServerException e) {
        return RR.exception(e.getMessage());
    }
    

    /**
     * @param e
     * @return
     * @Description 令牌校驗異常
     */
    @ExceptionHandler(ExpireException.class)
    public RR handleExpireException(ExpireException e) {
        return RR.expire(e.getMessage());
    }
    

    /**
     * @param e
     * @return
     * @Description 無權訪問異常
     */
    @ExceptionHandler(AccessDeniedException.class)
    public RR handleAccessDeniedException(AccessDeniedException e) {
        return RR.forbidden(e.getMessage());
    }
    

    /**
     * @param e
     * @return
     * @Description 自定義重複操做異常
     */
    public RR handleRepeatHandleException(RepeatHandleException e) {
        return RR.exception("您的請求已發送,請勿重複操做!");
    }
    

    /**
     * @param e
     * @return
     * @Description 登陸異常處理
     */
    @ExceptionHandler(AuthenticationException.class)
    public RR handleAuthenticationException(AuthenticationException e) {
        return RR.exception(e.getMessage());
    }

}

 

而後咱們用Swagger來測試一下接口數組

1.用戶名爲空app

 

2.手機號格式錯誤spring-boot

 

 

 

經過返回結果能夠看到,咱們的校驗註解已經幫咱們按照指定的校驗方式校驗了指定的字段屬性,咱們在統一的全局異常處理類中將提示信息封裝成須要的返回結果就能夠了。測試

 

分組校驗

有的童鞋在此可能有疑問了,上述方法雖然可行,但我在新增用戶和修改用戶兩個接口中,新增用戶的用戶id是自動生成的,無需校驗;修改用戶的用戶id是必傳的,則需校驗。在此業務場景中,那豈不是須要聲明兩個實體類,但這兩個實體類中的屬性又大體相同,這不是增長麻煩嗎?其實否則,在此咱們能夠用到groups屬性來解決此場景下的問題。spa

 

聲明分組

注意:在聲明分組的時候儘可能加上 extend javax.validation.groups.Default 不然,在你聲明@Validated(Update.class)的時候,就會出現你在默認沒添加groups = {}的時候的校驗組@Email(message = "郵箱格式不對"),會不去校驗,由於默認的校驗組是groups = {Default.class}。

/**
 * 數據新增分組
 */
public interface Create extends Default {

}


/**
 * 數據更新分組
 */
public interface Update extends Default {

}

 

校驗註解中添加分組,groups 爲一個數組,能夠添加多個分組

@NotNull(message = "id不能爲空" , groups = Update.class)
private Long id;

@NotBlank(message = "用戶名不能爲空" , groups = {Create.class, Update.class})
@Length(max = 10, message = "用戶名最長爲10位")
private String name;

 

修改Controller中的@Validated註解,聲明校驗分組

@PermissionCheck("account:manager:add")
@PostMapping(value = "/add", produces = BaseConsts.REQUEST_HEADERS_CONTENT_TYPE)
@ApiOperation(value = "用戶管理-添加用戶接口", notes = "用戶管理-添加用戶接口", httpMethod = BaseConsts.REQUEST_METHOD, response = RR.class)
public RR add(@Validated(Create.class) @RequestBody Account account) throws Exception {
    return RR.success("添加用戶成功");
}


@PermissionCheck("account:manager:edit")
@PostMapping(value = "/edit", produces = BaseConsts.REQUEST_HEADERS_CONTENT_TYPE)
@ApiOperation(value = "用戶管理-修改用戶接口", notes = "用戶管理-修改用戶接口", httpMethod = BaseConsts.REQUEST_METHOD, response = RR.class)
public RR edit(@Validated(Update.class) @RequestBody Account account) throws Exception {
    return RR.success("編輯用戶成功");
}

 

使用相同的請求參數測試一下添加用戶和修改用戶的接口

測試添加接口

 

 

 

 

測試修改接口

 

 

 

 

 

經過接口的返回結果能夠看到,新增用戶的接口並無校驗id這個參數了,而修改用戶的接口中則校驗了id不能爲空。

 

經常使用校驗註解

以上就是樓主在項目中使用validation的總結概括,下面收集了一些經常使用註解,紅色的標註則是樓主在項目中用的比較多的。

JSR提供的校驗註解:         
@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(regex)  被註釋的元素必須符合指定的正則表達式    


Hibernate Validator提供的校驗註解:  
@NotBlank()   驗證字符串非null且非空格,長度必須大於0    
@Email  被註釋的元素必須是電子郵箱地址    
@Length(min=,max=)  被註釋的字符串的大小必須在指定的範圍內    
@NotEmpty   被註釋的字符串的必須非空    
@Range(min=,max=,message=)  被註釋的元素必須在合適的範圍內

參考博文:https://blog.csdn.net/u013815546/article/details/77248003/

相關文章
相關標籤/搜索