java validation 后臺參數(shù)驗(yàn)證的使用詳解
一、前言
在后臺開發(fā)過程中,對參數(shù)的校驗(yàn)成為開發(fā)環(huán)境不可缺少的一個環(huán)節(jié)。比如參數(shù)不能為null,email那么必須符合email的格式,如果手動進(jìn)行if判斷或者寫正則表達(dá)式判斷無意開發(fā)效率太慢,在時(shí)間、成本、質(zhì)量的博弈中必然會落后。所以把校驗(yàn)層抽象出來是必然的結(jié)果,下面說下幾種解決方案。
二、幾種解決方案
1、struts2的valid可以通過配置xml,xml中描述規(guī)則和返回的信息,這種方式比較麻煩、開發(fā)效率低,不推薦
2、validation bean 是基于JSR-303標(biāo)準(zhǔn)開發(fā)出來的,使用注解方式實(shí)現(xiàn),及其方便,但是這只是一個接口,沒有具體實(shí)現(xiàn).Hibernate Validator是一個hibernate獨(dú)立的包,可以直接引用,他實(shí)現(xiàn)了validation bean同時(shí)有做了擴(kuò)展,比較強(qiáng)大 ,實(shí)現(xiàn)圖如下:
3、oval 是一個可擴(kuò)展的Java對象數(shù)據(jù)驗(yàn)證框架,驗(yàn)證的規(guī)則可以通過配置文件、Annotation、POJOs 進(jìn)行設(shè)定。可以使用純 Java 語言、JavaScript 、Groovy 、BeanShell 等進(jìn)行規(guī)則的編寫,本次不過多講解
三、bean validation 框架驗(yàn)證介紹
bean validation 包放在maven上維護(hù),最新包的坐標(biāo)如下:
<dependency> <groupId>javax.validation</groupId> <artifactId>validation-api</artifactId> <version>1.1.0.Final</version> </dependency>
下載之后打開這個包,有個package叫constraints,里面放的就是驗(yàn)證的的注解:
下面開始用代碼實(shí)踐一下:
1、定義一個待驗(yàn)證的bean:Student.java
package com.shishang; import javax.validation.constraints.*; import java.io.Serializable; import java.math.BigDecimal; import java.util.Date; public class Student implements Serializable { @NotNull(message = "名字不能為空") private String name; @Size(min = 6,max = 30,message = "地址應(yīng)該在6-30字符之間") private String address; @DecimalMax(value = "100.00",message = "體重有些超標(biāo)哦") @DecimalMin(value = "60.00",message = "多吃點(diǎn)飯吧") private BigDecimal weight; private String friendName; @AssertTrue private Boolean isHaveFriend(){ return friendName != null?true:false; } @Future(message = "生日必須在當(dāng)前實(shí)踐之前") private Date birthday; @Pattern(regexp = "^(.+)@(.+)$",message = "郵箱的格式不合法") private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public BigDecimal getWeight() { return weight; } public void setWeight(BigDecimal weight) { this.weight = weight; } public String getFriendName() { return friendName; } public void setFriendName(String friendName) { this.friendName = friendName; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
2、測試類:StudentTest.java
package com.use; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import java.io.Serializable; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; public class StudentTest implements Serializable { public static void main(String[] args) { Student xiaoming = getBean(); List<String> validate = validate(xiaoming); validate.forEach(row -> { System.out.println(row.toString()); }); } private static Student getBean() { Student bean = new Student(); bean.setName(null); bean.setAddress("北京"); bean.setBirthday(new Date()); bean.setFriendName(null); bean.setWeight(new BigDecimal(30)); bean.setEmail("xiaogangfan163.com"); return bean; } private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); public static <T> List<String> validate(T t) { Validator validator = factory.getValidator(); Set<ConstraintViolation<T>> constraintViolations = validator.validate(t); List<String> messageList = new ArrayList<>(); for (ConstraintViolation<T> constraintViolation : constraintViolations) { messageList.add(constraintViolation.getMessage()); } return messageList; } }
3、運(yùn)行testValidation()方法,輸處如下:
- 地址應(yīng)該在6-30字符之間
- 郵箱的格式不合法
- 生日必須在當(dāng)前時(shí)間之前
- 多吃點(diǎn)飯吧
- 名字不能為空
4、總結(jié)
- 像@NotNull、@Size等比較簡單也易于理解,不多說
- 因?yàn)閎ean validation只提供了接口并未實(shí)現(xiàn),使用時(shí)需要加上一個provider的包,例如hibernate-validator
- @Pattern 因?yàn)檫@個是正則,所以能做的事情比較多,比如中文還是數(shù)字、郵箱、長度等等都可以做
- @AssertTRue 這個與其他的校驗(yàn)注解有著本質(zhì)的區(qū)別,這個注解適用于多個字段。例子中isHaveFriend方法依賴friendName字段校驗(yàn)
- 驗(yàn)證的api是經(jīng)過我加工了一下,這樣可以批量返回校驗(yàn)的信息
- 有時(shí)我們需要的注解可能沒有提供,這時(shí)候就需要自定義注解,寫實(shí)現(xiàn)類,下面說一下自定義注解的使用
四、自定義bean validation 注解驗(yàn)證
有時(shí)框架自帶的沒法滿足我們的需求,這時(shí)就需要自己動手豐衣足食了,恩恩 ,這個不難,下面說下。
這個例子驗(yàn)證字符串是大寫還是小寫約束標(biāo)注,代碼如下:
1、枚舉類型CaseMode, 來表示大寫或小寫模式
package com.defineconstrain; /** * created by xiaogangfan * on 16/10/25. */ public enum CaseMode { UPPER, LOWER; }
2、定義一個CheckCase的約束標(biāo)注
package com.defineconstrain; /** * created by xiaogangfan * on 16/10/25. */ import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) @Documented public @interface CheckCase { String message() default "{com.mycompany.constraints.checkcase}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; CaseMode value(); }
3、約束條件CheckCase的驗(yàn)證器
package com.defineconstrain; /** * created by xiaogangfan * on 16/10/25. */ import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private CaseMode caseMode; public void initialize(CheckCase constraintAnnotation) { this.caseMode = constraintAnnotation.value(); } public boolean isValid(String object, ConstraintValidatorContext constraintContext) { if (object == null) return true; if (caseMode == CaseMode.UPPER) return object.equals(object.toUpperCase()); else return object.equals(object.toLowerCase()); } }
4、在Student.java中增加一個屬性
@CheckCase(value = CaseMode.LOWER,message = "名字的拼音需要小寫") private String spellName;
5、在StudentTest.java的getBean()方法中增加一行
bean.setSpellName("XIAOGANGFAN");
6、運(yùn)行testValidation()方法,輸處如下:
- 地址應(yīng)該在6-30字符之間
- 郵箱的格式不合法
- 生日必須在當(dāng)前時(shí)間之前
- 多吃點(diǎn)飯吧
- 名字的拼音需要小寫
- 名字不能為空
7、說明新增的約束生效了,大功告成
代碼下載地址:git@github.com:xiaogangfan/vaidation.git
命令: git clone git@github.com:xiaogangfan/vaidation.git
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot中捕獲異常錯誤信息并將其保存到數(shù)據(jù)庫中的操作方法
這篇文章主要介紹了Spring Boot中捕獲異常錯誤信息并將其保存到數(shù)據(jù)庫中的操作方法,通過實(shí)例代碼介紹了使用Spring Data JPA創(chuàng)建一個異常信息的存儲庫接口,以便將異常信息保存到數(shù)據(jù)庫,需要的朋友可以參考下2023-10-10java中Class.getMethods()和Class.getDeclaredMethods()方法的區(qū)別
這篇文章主要介紹了java中Class.getMethods()和Class.getDeclaredMethods()方法的區(qū)別 ,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09Java類的定義以及執(zhí)行順序?qū)W習(xí)教程
這篇文章主要介紹了Java類的定義以及執(zhí)行順序?qū)W習(xí)教程,包括對象的創(chuàng)建等面向?qū)ο缶幊痰幕A(chǔ)知識,需要的朋友可以參考下2015-09-09