摘要:所以就有今天的話題利用注解對進行校驗。利用注解對進行校驗,主要是利用框架,實現了的接口關于校驗的接口,直接使用非常方便,省時省力。
最近寫業務代碼,因為頁面復雜,導致對應的Bean屬性非常多,而產品大佬又提出各種校驗要求。
emmmmmm......如果寫if條件來校驗,那簡直是又臭又長。
所以就有今天的話題——利用注解對Bean進行校驗。
利用注解對Bean進行校驗,主要是利用hibernate-validator框架,hibernate-validator實現了validation-api的接口關于Bean校驗的接口,直接使用hibernate-validator非常方便,省時省力。
1.hibernate-validato簡介此hibernate-validator+SpringMVC可以實現以下功能:
注解java bean聲明校驗規則;
添加message錯誤信息源實現國際化配置;
結合spring form中的errors標簽展現錯誤信息。
優勢:
代碼簡潔、處理校驗可以更加優雅。
實現要求:
使用hibernate validator至少要引入兩個jar包:
org.hibernate.validator hibernate-validator 6.0.1.Final org.glassfish javax.el 3.0.1-b08
java bean中使用注解添加檢驗規則。
2.注解及用法hibernate validator使用的注解定義在hibernate-validator-6.0.1.Final.jar、validation-api-1.1.0.Final.jar兩個包中,
@AssertFalse 驗證注解的元素值是false @AssertTrue 驗證注解的元素值是true @DecimalMax(value=x) 驗證注解的元素值小于等于@ DecimalMax指定的value值 @DecimalMin(value=x) 驗證注解的元素值小于等于@ DecimalMin指定的value值 @Digits(integer=整數位數, fraction=小數位數) 驗證注解的元素值的整數位數和小數位數上限 @Future 驗證注解的元素值(日期類型)比當前時間晚 @Max(value=x) 驗證注解的元素值小于等于@Max指定的value值 @Min(value=x) 驗證注解的元素值大于等于@Min指定的value值 @NotNull 驗證注解的元素值不是null @Null 驗證注解的元素值是null @Past 驗證注解的元素值(日期類型)比當前時間早 @Pattern(regex=正則表達式, flag=) 驗證注解的元素值與指定的正則表達式匹配 @Size(min=最小值, max=最大值) 驗證注解的元素值的在min和max(包含)指定區間之內,如字符長度、集合大小 @Valid 驗證關聯的對象,如賬戶對象里有一個訂單對象,指定驗證訂單對象 @NotEmpty 驗證注解的元素值不為null且不為空(字符串長度不為0、集合大小不為0) @Range(min=最小值, max=最大值) 驗證注解的元素值在最小值和最大值之間 @NotBlank 驗證注解的元素值不為空(不為null、去除首位空格后長度為0),不同于@NotEmpty,@NotBlank只應用于字符串且在比較時會去除字符串的空格 @Length(min=下限, max=上限) 驗證注解的元素值長度在min和max區間內 @Email 驗證注解的元素值是Email,也可以通過正則表達式和flag指定自定義的email格式3.校驗demo
利用hibernate validator實現Bean校驗,一般有兩種做法:
利用@ModelAttribute和@Valid注解;
利用validate()、validateValue()、validateProperty()等方法在需要之處直接調用。
Bean對象:
import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } //getters and setters ... }3.1.利用Validator的validate()方法
驗證器
import org.apache.commons.collections4.CollectionUtils; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.Set; public class ValidateTest { /** * 驗證器 */ private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); public static void main(String[] args) { Car car = new Car(null, "12", 1); //執行驗證 Set> constraintViolations = validator.validate(car); //打印校驗信息 if (CollectionUtils.isNotEmpty(constraintViolations)) { for (ConstraintViolation constraintViolation : constraintViolations) { System.out.println(constraintViolation.getPropertyPath().toString() + ": " + constraintViolation.getMessage()); } } } }
輸出結果:
seatCount: 最小不能小于2 manufacturer: 不能為null3.2.利用@ModelAttribute和@Valid注解和BindingResult對象
校驗demo
import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import javax.validation.Valid; @Controller("/Validate") public class ValidateTestController { @RequestMapping("/demo1") public void validateDemo(@Valid @ModelAttribute("car") Car car, BindingResult result) { if(result.hasErrors()){ for (ObjectError error : result.getAllErrors()) { System.out.println(error.getDefaultMessage()); } } } }
測試數據:
{ "manufacturer": null, "licensePlate": "", "seatCount": 1 }
結果:
不能為null 個數必須在2和14之間 最小不能小于2
注意,需要加上@ModelAttribute注解,否則會報錯: An Error/BindingResult argument is3.3.利用@Valid注解和統一異常處理
expected to be declared immediately after the model attribute
校驗demo
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.validation.Valid; @Controller @RequestMapping("/validate") public class ValidateTestController { @RequestMapping("/demo1") public void validateDemo(@Valid Car car) { } }
測試數據:
{ "manufacturer": null, "licensePlate": "", "seatCount": 1 }
統一異常處理類:
@Component public class ExceptionResolver implements HandlerExceptionResolver { /** * 日志 */ private static final Logger LOG = LoggerFactory.getLogger(AuditCommonExceptionResolver.class); @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { if (ex instanceof BindException) { BindException exs = (BindException) ex; for (ObjectError o : exs.getAllErrors()) { System.out.println(o.getDefaultMessage()); } } else if (ex instanceof ConstraintViolationException) { ConstraintViolationException exs = (ConstraintViolationException) ex; Set> violations = exs.getConstraintViolations(); for (ConstraintViolation> item : violations) { System.out.println(item.getMessage()); } } else { LOG.error("捕獲未處理異常,異常信息:{}", ex.getMessage()); } return new ModelAndView("/sys/errorPage.jsp"); } }
結果:
不能為null 個數必須在2和14之間 最小不能小于2
注意:我自己測試的時候,捕獲的是BindException異常,但是看網上好多文章寫的都是捕獲ConstraintViolationException異常,
比較以上三種校驗方式(準確的說應該是三種hibernate validator的使用方式),可以發現2、3大同小異,使用@Valid可以不用再自己寫校驗的處理方法,但是方式1可以更加靈活,可以按照自己需求處理和組織校驗的返回信息。
4.hibernate validator更詳細的使用文檔hibernate validator的更詳細的使用說明,可以參考官方文檔,以前沒關注,這次認真的看了一下,發現hibernate validator的功能還是很強大的,最新的5.0、6.0版本只有英文文檔,4.0版本有中文文檔。地址如下:https://docs.jboss.org/hibern...
5.使用過程中遇到的問題使用方式1,在我自己電腦注解沒有添加message信息時,默認返回的是中文,如@NotNull:不能為null,@NotEmpty:不能為空等等,但是,當部署到服務器以后,就變成英文,如@NotNull:may not be null,@NotEmpty:may not be empty等等,很是詭異。后來研讀源碼發現,hibernate validator通過messageInterpolator字段來實現國際化的,messageInterpolator字段中存放著當前操作系統的語言環境參數,然后根據語言環境參數去對應的配置文檔中讀取默認提示信息,而messageInterpolator則會在項目啟動時初始化,因為我自己的電腦是中文環境,而公司的系統環境是英文的,所以導致這個問題。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75290.html
摘要:如果說要使用數據校驗,我十分相信小伙伴們都能夠使用,但估計大都是有個前提的環境。具體使用可參考小家讓支持對平鋪參數執行數據校驗默認使用只能對進行校驗級聯校驗什么叫級聯校驗,其實就是帶校驗的成員里存在級聯對象時,也要對它完成校驗。 每篇一句 NBA里有兩大笑話:一是科比沒天賦,二是詹姆斯沒技術 相關閱讀 【小家Java】深入了解數據校驗:Java Bean Validation 2.0(...
摘要:我們可不可以提供一個公共的入口進行統一的異常處理呢當然可以。一般我們可以在地址上帶上版本號,也可以在參數上帶上版本號,還可以再里帶上版本號,這里我們在地址上帶上版本號,大致的地址如,其中,即代表的是版本號。 上一篇帶領大家初步了解了如何使用 Spring Boot 搭建框架,通過 Spring Boot 和傳統的 SpringMVC 架構的對比,我們清晰地發現 Spring Boot ...
摘要:和上標注的約束都會被執行注意如果子類覆蓋了父類的方法,那么子類和父類的約束都會被校驗。 每篇一句 沒有任何技術方案會是一種銀彈,任何東西都是有利弊的 相關閱讀 【小家Java】深入了解數據校驗:Java Bean Validation 2.0(JSR303、JSR349、JSR380)Hibernate-Validation 6.x使用案例【小家Spring】Spring方法級別數據校...
摘要:動態代理的核心是接口和類。以上結果說明它生成的代理類為,說明是代理。測試前提實現接口測試類使用接口方式注入代理方式必須以接口方式注入測試配置為,運行結果如下實際校驗邏輯。。。。 本文也同步發布至簡書,地址:https://www.jianshu.com/p/f70... AOP設計模式通常運用在日志,校驗等業務場景,本文將簡單介紹基于Spring的AOP代理模式的運用。 1. 代理模...
摘要:前言估計很多朋友都認為參數校驗是客戶端的職責,不關服務端的事。輕則導致服務器宕機,重則泄露數據。所以,這時就需要設置第二道關卡,服務端驗證了。老項目的服務端校驗不能為空不能為空看以上代碼,就一個的校驗就如此麻煩。 前言 估計很多朋友都認為參數校驗是客戶端的職責,不關服務端的事。其實這是錯誤的,學過 Web 安全的都知道,客戶端的驗證只是第一道關卡。它的參數驗證并不是安全的,一旦被有心人...
閱讀 1765·2021-09-22 15:10
閱讀 1261·2021-09-07 09:58
閱讀 2333·2019-08-30 15:44
閱讀 1634·2019-08-26 18:29
閱讀 2033·2019-08-26 13:35
閱讀 758·2019-08-26 13:31
閱讀 719·2019-08-26 11:42
閱讀 1065·2019-08-23 18:39