java validation 后臺(tái)參數(shù)驗(yàn)證的使用詳解
一、前言
在后臺(tái)開(kāi)發(fā)過(guò)程中,對(duì)參數(shù)的校驗(yàn)成為開(kāi)發(fā)環(huán)境不可缺少的一個(gè)環(huán)節(jié)。比如參數(shù)不能為null,email那么必須符合email的格式,如果手動(dòng)進(jìn)行if判斷或者寫(xiě)正則表達(dá)式判斷無(wú)意開(kāi)發(fā)效率太慢,在時(shí)間、成本、質(zhì)量的博弈中必然會(huì)落后。所以把校驗(yàn)層抽象出來(lái)是必然的結(jié)果,下面說(shuō)下幾種解決方案。
二、幾種解決方案
1、struts2的valid可以通過(guò)配置xml,xml中描述規(guī)則和返回的信息,這種方式比較麻煩、開(kāi)發(fā)效率低,不推薦
2、validation bean 是基于JSR-303標(biāo)準(zhǔn)開(kāi)發(fā)出來(lái)的,使用注解方式實(shí)現(xiàn),及其方便,但是這只是一個(gè)接口,沒(méi)有具體實(shí)現(xiàn).Hibernate Validator是一個(gè)hibernate獨(dú)立的包,可以直接引用,他實(shí)現(xiàn)了validation bean同時(shí)有做了擴(kuò)展,比較強(qiáng)大 ,實(shí)現(xiàn)圖如下:

3、oval 是一個(gè)可擴(kuò)展的Java對(duì)象數(shù)據(jù)驗(yàn)證框架,驗(yàn)證的規(guī)則可以通過(guò)配置文件、Annotation、POJOs 進(jìn)行設(shè)定??梢允褂眉?Java 語(yǔ)言、JavaScript 、Groovy 、BeanShell 等進(jìn)行規(guī)則的編寫(xiě),本次不過(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>
下載之后打開(kāi)這個(gè)包,有個(gè)package叫constraints,里面放的就是驗(yàn)證的的注解:
下面開(kāi)始用代碼實(shí)踐一下:
1、定義一個(gè)待驗(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、測(cè)試類(lèi):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等比較簡(jiǎn)單也易于理解,不多說(shuō)
- 因?yàn)閎ean validation只提供了接口并未實(shí)現(xiàn),使用時(shí)需要加上一個(gè)provider的包,例如hibernate-validator
- @Pattern 因?yàn)檫@個(gè)是正則,所以能做的事情比較多,比如中文還是數(shù)字、郵箱、長(zhǎng)度等等都可以做
- @AssertTRue 這個(gè)與其他的校驗(yàn)注解有著本質(zhì)的區(qū)別,這個(gè)注解適用于多個(gè)字段。例子中isHaveFriend方法依賴(lài)friendName字段校驗(yàn)
- 驗(yàn)證的api是經(jīng)過(guò)我加工了一下,這樣可以批量返回校驗(yàn)的信息
- 有時(shí)我們需要的注解可能沒(méi)有提供,這時(shí)候就需要自定義注解,寫(xiě)實(shí)現(xiàn)類(lèi),下面說(shuō)一下自定義注解的使用
四、自定義bean validation 注解驗(yàn)證
有時(shí)框架自帶的沒(méi)法滿(mǎn)足我們的需求,這時(shí)就需要自己動(dòng)手豐衣足食了,恩恩 ,這個(gè)不難,下面說(shuō)下。
這個(gè)例子驗(yàn)證字符串是大寫(xiě)還是小寫(xiě)約束標(biāo)注,代碼如下:
1、枚舉類(lèi)型CaseMode, 來(lái)表示大寫(xiě)或小寫(xiě)模式
package com.defineconstrain;
/**
* created by xiaogangfan
* on 16/10/25.
*/
public enum CaseMode {
UPPER,
LOWER;
}
2、定義一個(gè)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中增加一個(gè)屬性
@CheckCase(value = CaseMode.LOWER,message = "名字的拼音需要小寫(xiě)") private String spellName;
5、在StudentTest.java的getBean()方法中增加一行
bean.setSpellName("XIAOGANGFAN");
6、運(yùn)行testValidation()方法,輸處如下:
- 地址應(yīng)該在6-30字符之間
- 郵箱的格式不合法
- 生日必須在當(dāng)前時(shí)間之前
- 多吃點(diǎn)飯吧
- 名字的拼音需要小寫(xiě)
- 名字不能為空
7、說(shuō)明新增的約束生效了,大功告成
代碼下載地址:git@github.com:xiaogangfan/vaidation.git
命令: git clone git@github.com:xiaogangfan/vaidation.git
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Springboot項(xiàng)目javax.validation使用方法詳解
- java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的方式總結(jié)
- JAVA中通過(guò)Hibernate-Validation進(jìn)行參數(shù)驗(yàn)證
- JAVA中的字段校驗(yàn)(validation)
- 使用javax.validation.constraints對(duì)請(qǐng)求體進(jìn)行統(tǒng)一校驗(yàn)
- Java參數(shù)校驗(yàn)中validation和validator的區(qū)別詳解
- Java Validation Api實(shí)現(xiàn)原理解析
- Java Validation Api如何實(shí)現(xiàn)自定義注解
- Javax Validation自定義注解進(jìn)行身份證號(hào)校驗(yàn)
- Java使用validation攔截非法提交的數(shù)據(jù)的方法實(shí)現(xiàn)
相關(guān)文章
springboot讀取application.yml報(bào)錯(cuò)問(wèn)題及解決
這篇文章主要介紹了springboot讀取application.yml報(bào)錯(cuò)問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
javaWEB中前后臺(tái)亂碼問(wèn)題的解決方法總結(jié)
下面小編就為大家?guī)?lái)一篇javaWEB中前后臺(tái)亂碼問(wèn)題的解決方法總結(jié)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
SpringBoot中的ExpiringMap代碼實(shí)例
這篇文章主要介紹了SpringBoot中的ExpiringMap代碼實(shí)例,ExpiringMap是一個(gè)可以設(shè)置過(guò)期策略、可變條目過(guò)期、延遲條目加載和過(guò)期偵聽(tīng)器的線(xiàn)程安全存儲(chǔ)容器,需要的朋友可以參考下2023-08-08
Java?詳解Collection集合之ArrayList和HashSet
本章具體介紹了ArrayList和HashSet兩種集合的基本使用方法和區(qū)別,圖解穿插代碼實(shí)現(xiàn)。?JAVA成仙路從基礎(chǔ)開(kāi)始講,后續(xù)會(huì)講到JAVA高級(jí),中間會(huì)穿插面試題和項(xiàng)目實(shí)戰(zhàn),希望能給大家?guī)?lái)幫助2022-03-03
淺談PrintStream和PrintWriter的區(qū)別和聯(lián)系
這篇文章主要介紹了淺談PrintStream和PrintWriter的區(qū)別和聯(lián)系,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
探索Java中private方法添加@Transactional事務(wù)未生效原因
你又遇到過(guò)明明給private方法添加了@Transactional但是事務(wù)依然沒(méi)有生效的情況嗎,具體原因本篇文章將詳細(xì)告訴你,有需要的朋友跟著小編往下看吧2021-11-11

