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

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

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

服務器之家 - 編程語言 - Java教程 - 如何使用Bean Validation 解決業務中參數校驗

如何使用Bean Validation 解決業務中參數校驗

2021-10-26 10:28Hi-Sunshine Java教程

這篇文章主要介紹了如何使用Bean Validation 解決業務中參數校驗操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

前言

在開發中經常需要寫一些字段校驗的代碼,比如字段非空,字段長度限制,郵箱格式驗證等等,寫這些與業務邏輯關系不大的代碼個人感覺有點麻煩:

驗證代碼繁瑣,重復勞動

方法內代碼顯得冗長

每次要看哪些參數驗證是否完整,需要去翻閱驗證邏輯代碼

敘述

Bean Validation是一個通過配置注解來驗證參數的框架,它包含兩部分Bean Validation API和Hibernate Validator。

Bean Validation API是Java定義的一個驗證參數的規范。

Hibernate Validator是Bean Validation API的一個實現。

@Valid和Validated的比較

Spring Validation驗證框架對參數的驗證機制提供了@Validated(Spring's JSR-303規范,是標準JSR-303的一個變種),javax提供了@Valid(標準JSR-303規范),配合BindingResult可以直接提供參數驗證結果。

@Valid : 沒有分組功能,可以用在方法、構造函數、方法參數和成員屬性(field)上,如果一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@valid,才能驗證待驗證對象中的成員屬性

@Validated :提供分組功能,可以在入參驗證時,根據不同的分組采用不同的驗證機制,用在類型、方法和方法參數上。但不能用于成員屬性(field)。

兩者都可以用在方法入參上,但都無法單獨提供嵌套驗證功能,都能配合嵌套驗證注解@Valid進行嵌套驗證。

嵌套驗證示例:

?
1
2
3
4
5
6
7
8
public class ClassRoom{
    @NotNull
    String name;
    
    @Valid  // 嵌套校驗,校驗參數內部的屬性
    @NotNull
    Student student;
}
?
1
2
3
4
5
6
7
@GetMapping("/room")   // 此處可使用 @Valid 或 @Validated, 將會進行嵌套校驗
  public String validator(@Validated ClassRoom classRoom, BindingResult result) {
      if (result.hasErrors()) {
          return result.getFieldError().getDefaultMessage();
      }
      return "ok";
  }

BindingResult 的使用

BindingResult必須跟在被校驗參數之后,若被校驗參數之后沒有BindingResult對象,將會拋出BindException。

?
1
2
3
4
5
6
7
@GetMapping("/room")
    public String validator(@Validated ClassRoom classRoom, BindingResult result) {
        if (result.hasErrors()) {
            return result.getFieldError().getDefaultMessage();
        }
        return "ok";
    }

不要使用 BindingResult 接收String等簡單對象的錯誤信息。簡單對象校驗失敗,會拋出 ConstraintViolationException。主要就是接不著,你要寫也算是沒關系…

?
1
2
3
4
5
6
7
8
9
// ? 錯誤用法,也沒有特別的錯,只是 result 是接不到值。
  @GetMapping("/room")
  @Validated  // 啟用校驗
  public String validator(@NotNull String name, BindingResult result) {
      if (result.hasErrors()) {
          return result.getFieldError().getDefaultMessage();
      }
      return "ok";
  }

修改校驗失敗的提示信息

可以通過各個校驗注解的message屬性設置更友好的提示信息。

?
1
2
3
4
5
6
7
8
public class ClassRoom{
    @NotNull(message = "Classroom name must not be null")
    String name;
    
    @Valid
    @NotNull
    Student student;
}
?
1
2
3
4
5
6
7
8
@GetMapping("/room")
   @Validated
   public String validator(ClassRoom classRoom, BindingResult result, @NotNull(message = "姓名不能為空") String name) {
       if (result.hasErrors()) {
           return result.getFieldError().getDefaultMessage();
       }
       return "ok";
   }

message屬性配置國際化的消息也可以的,message中填寫國際化消息的code,在拋出異常時根據code處理一下就好了。

?
1
2
3
4
5
6
7
8
@GetMapping("/room")
    @Validated
    public String validator(@NotNull(message = "demo.message.notnull") String name) {
        if (result.hasErrors()) {
            return result.getFieldError().getDefaultMessage();
        }
        return "ok";
    }
?
1
2
3
4
5
// message_zh_CN.properties
demo.message.notnull=xxx消息不能為空
 
// message_en_US.properties
demo.message.notnull=xxx message must no be null

hibernate-validator 的使用

1.引入pom

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

2.dto入參對象屬性加入注解

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Data
public class UserModel implements Serializable {
    private String id;
    @NotBlank(message = "用戶名不能為空")
    private String name;
 
    @NotNull(message = "性別不能不填")
    private Byte gender;
 
    @NotNull(message = "年齡不能不填")
    @Min(value = 0,message = "年齡必須大于0歲")
    @Max(value = 150,message = "年齡必須小于150歲")
    private Integer age;
    
    @NotBlank(message = "手機號不能不填")
    private String telphone;
    
    private String registerMode;
    private String thirdPartyId;
    private String encrptPassward;
}

方法一:3.controller方法入參加入校驗(@Validated )

?
1
2
3
4
5
6
7
@GetMapping("/getUser")
    public String validator(@Validated UserModel userModel , BindingResult result) {
        if (result.hasErrors()) {
            return result.getFieldError().getDefaultMessage();
        }
        return "ok";
    }

方法二:3.自定義封裝ValidatorImpl類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class ValidatorImpl implements InitializingBean{
 
    private Validator validator;
 
    //實現校驗方法并返回校驗結果
    public ValidationResult validate(Object bean){
        final   ValidationResult result=new ValidationResult();
        Set<ConstraintViolation<Object>> validate = validator.validate(bean);
        if (validate.size()>0) {
            result.setHasError(true);
            validate.forEach(constraintViolation->{
                String errMsg=constraintViolation.getMessage();
                String propertyName=constraintViolation.getPropertyPath().toString();
                result.getErrorMsgMap().put(propertyName,errMsg);
            });
        }
        return result;
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        this.validator= Validation.buildDefaultValidatorFactory().getValidator();
    }
}

方法二:4.自定義封裝ValidationResult 類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ValidationResult {
    public boolean hasError=false;
    private Map<String,String> errorMsgMap=new HashMap<>();
 
    //實現通用的通過格式化字符串信息獲取錯誤結果的msg方法
    public String getErrMsg(){
        return StringUtils.join(errorMsgMap.values().toArray(),",");
    }
 
    public boolean isHasError() {
        return hasError;
    }
 
    public void setHasError(boolean hasError) {
        this.hasError = hasError;
    }
 
    public Map<String, String> getErrorMsgMap() {
        return errorMsgMap;
    }
 
    public void setErrorMsgMap(Map<String, String> errorMsgMap) {
        this.errorMsgMap = errorMsgMap;
    }
}

5.controller方法入參加入校驗

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Autowired
 private ValidatorImpl validator;
  @Override
     @Transactional(rollbackFor = Exception.class)
  public void register(UserModel userModel) throws BusinessException {
      UserDo userDo=new UserDo();
      if (userModel == null) {
          throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR);
      }
 
//validate進行入參校驗
     ValidationResult validate = validator.validate(userModel);
      if (validate.isHasError()){
          throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,validate.getErrMsg());
      }
  }

Bean Validation 的約束

  • @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 附加的約束

Hibernate Validator 附加的 constraint:

  • @Email 被注釋的元素必須是電子郵箱地址
  • @Length 被注釋的字符串的大小必須在指定的范圍內
  • @NotEmpty 被注釋的字符串的必須非空
  • @Range 被注釋的元素必須在合適的范圍內

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/zmh458/article/details/96173583

延伸 · 閱讀

精彩推薦
  • Java教程20個非常實用的Java程序代碼片段

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

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

    lijiao5352020-04-06
  • Java教程升級IDEA后Lombok不能使用的解決方法

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

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

    程序猿DD9332021-10-08
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

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

    Java教程網2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

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

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

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

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

    大行者10067412021-08-30
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

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

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

    小米推送Java代碼

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

    富貴穩中求8032021-07-12
  • Java教程Java8中Stream使用的一個注意事項

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

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

    阿杜7472021-02-04
主站蜘蛛池模板: 欧美a欧美1级 | 天堂资源在线www中文 | tube8老师| 国产精品久久久久久久人人看 | 女同69式互添在线观看免费 | 色吧导航 | 亚洲高清无在码在线电影 | 激情视频亚洲 | 麻豆在线md0087免费 | 爽爽影院免费观看 | 免费特黄一级欧美大片 | 国产成人精品免费 | 99爱在线观看精品视频 | 娇女的呻吟亲女禁忌h16 | 四虎精品成人免费观看 | 亚洲国产在线综合018 | 亚洲精品AV无码喷奶水糖心 | 色综合色狠狠天天综合色 | 欧美高清乌克兰精品另类 | 日本亚洲欧洲高清有码在线播放 | 99在线免费视频 | 精品国产视频 | 99精品观看 | 久久婷婷五月综合色丁香 | 乌克兰精品摘花处破 | 91大神大战高跟丝袜美女 | 狠狠的撞进去嗯啊h女强男视频 | 国产精品女同久久免费观看 | 草草草视频在线观看 | 国产东北3p真实在线456视频 | 国产精品露脸国语对白河北 | 久久受www免费人成_看片中文 | 亚洲国产剧情中文视频在线 | 亚洲无人区乱码中文字幕 | 免费视频精品一区二区三区 | 亚洲成人免费观看 | 国内亚州视频在线观看 | 久久99r66热这里只有精品 | 亚洲第一天堂无码专区 | 亚洲高清网站 | 欧美视频在线一区二区三区 |