您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關怎么使用Bean Validation解決業務中參數校驗,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Bean Validation是一個通過配置注解來驗證參數的框架,它包含兩部分Bean Validation API和Hibernate Validator。
Bean Validation API是Java定義的一個驗證參數的規范。
Hibernate Validator是Bean Validation API的一個實現。
Spring Validation驗證框架對參數的驗證機制提供了@Validated(Spring's JSR-303規范,是標準JSR-303的一個變種),javax提供了@Valid(標準JSR-303規范),配合BindingResult可以直接提供參數驗證結果。
@Valid : 沒有分組功能,可以用在方法、構造函數、方法參數和成員屬性(field)上,如果一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@valid,才能驗證待驗證對象中的成員屬性
@Validated :提供分組功能,可以在入參驗證時,根據不同的分組采用不同的驗證機制,用在類型、方法和方法參數上。但不能用于成員屬性(field)。
兩者都可以用在方法入參上,但都無法單獨提供嵌套驗證功能,都能配合嵌套驗證注解@Valid進行嵌套驗證。
嵌套驗證示例:
public class ClassRoom{ @NotNull String name; @Valid // 嵌套校驗,校驗參數內部的屬性 @NotNull Student student; }
@GetMapping("/room") // 此處可使用 @Valid 或 @Validated, 將會進行嵌套校驗 public String validator(@Validated ClassRoom classRoom, BindingResult result) { if (result.hasErrors()) { return result.getFieldError().getDefaultMessage(); } return "ok"; }
BindingResult必須跟在被校驗參數之后,若被校驗參數之后沒有BindingResult對象,將會拋出BindException。
@GetMapping("/room") public String validator(@Validated ClassRoom classRoom, BindingResult result) { if (result.hasErrors()) { return result.getFieldError().getDefaultMessage(); } return "ok"; }
不要使用 BindingResult 接收String等簡單對象的錯誤信息。簡單對象校驗失敗,會拋出 ConstraintViolationException。主要就是接不著,你要寫也算是沒關系…
// ? 錯誤用法,也沒有特別的錯,只是 result 是接不到值。 @GetMapping("/room") @Validated // 啟用校驗 public String validator(@NotNull String name, BindingResult result) { if (result.hasErrors()) { return result.getFieldError().getDefaultMessage(); } return "ok"; }
修改校驗失敗的提示信息
可以通過各個校驗注解的message屬性設置更友好的提示信息。
public class ClassRoom{ @NotNull(message = "Classroom name must not be null") String name; @Valid @NotNull Student student; }
@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處理一下就好了。
@GetMapping("/room") @Validated public String validator(@NotNull(message = "demo.message.notnull") String name) { if (result.hasErrors()) { return result.getFieldError().getDefaultMessage(); } return "ok"; }
// message_zh_CN.properties demo.message.notnull=xxx消息不能為空 // message_en_US.properties demo.message.notnull=xxx message must no be null
1.引入pom
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.3.1.Final</version> </dependency>
2.dto入參對象屬性加入注解
@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 )
@GetMapping("/getUser") public String validator(@Validated UserModel userModel , BindingResult result) { if (result.hasErrors()) { return result.getFieldError().getDefaultMessage(); } return "ok"; }
方法二:3.自定義封裝ValidatorImpl類
@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 類
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方法入參加入校驗
@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()); } }
@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 附加的 constraint:
@Email
被注釋的元素必須是電子郵箱地址
@Length
被注釋的字符串的大小必須在指定的范圍內
@NotEmpty
被注釋的字符串的必須非空
@Range
被注釋的元素必須在合適的范圍內
關于“怎么使用Bean Validation解決業務中參數校驗”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。