JAVA中的字段校驗(yàn)(validation)
在開(kāi)發(fā)業(yè)務(wù)時(shí),不可避免的需要處理一些校驗(yàn), 如果是寫(xiě)if-else這種代碼去校驗(yàn), 那會(huì)有一大段這樣的代碼。
不過(guò)還好有個(gè)校驗(yàn)插件:javax.validation.validation-api,不過(guò)一般會(huì)引用hibernate的校驗(yàn)組件:org.hibernate.hibernate-validator, 它已經(jīng)引用了validation-api組件。
基礎(chǔ)校驗(yàn)類型
JSR303 是一套JavaBean參數(shù)校驗(yàn)的標(biāo)準(zhǔn),它定義了很多常用的校驗(yàn)注解,我們可以直接將這些注解加在我們JavaBean的屬性上面,就可以在需要校驗(yàn)的時(shí)候進(jìn)行校驗(yàn)了。
注解如下:

Hibernate validator 在JSR303的基礎(chǔ)上對(duì)校驗(yàn)注解進(jìn)行了擴(kuò)展,擴(kuò)展注解如下:

寫(xiě)個(gè)DEMO看看
校驗(yàn)工具類:ValidatorUtils
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Created by saleson on 2017/10/13.
*/
public class ValidatorUtils {
private static Validator validator = Validation.buildDefaultValidatorFactory()
.getValidator();
public static <T> Map<String, String> validate(T obj) {
Map<String, StringBuilder> errorMap = new HashMap<>();
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);
if (set != null && set.size() > 0) {
String property = null;
for (ConstraintViolation<T> cv : set) {
//這里循環(huán)獲取錯(cuò)誤信息,可以自定義格式
property = cv.getPropertyPath().toString();
if (errorMap.get(property) != null) {
errorMap.get(property).append("," + cv.getMessage());
} else {
StringBuilder sb = new StringBuilder();
sb.append(cv.getMessage());
errorMap.put(property, sb);
}
}
}
return errorMap.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().toString()));
}
}DemoBean:
import com.fm.core.exceptions.ApiException;
import org.hibernate.validator.constraints.NotEmpty;
import com.fm.framework.api.ApiResultHelper;
import com.fm.framework.json.Json;
import com.fm.framework.utils.StringUtils;
import com.fm.grantauth.domain.ValidateResult;
import com.fm.grantauth.domain.dto.AuthorizationApplyDTO;
import com.fm.grantauth.utils.ValidatorUtils;
import org.junit.Test;
import javax.validation.Valid;
import java.util.Map;
/**
* Created by saleson on 2017/10/12.
*/
public class DataAuthValidator {
private static final Logger log = LoggerFactory.getLogger(DataAuthValidator.class);
@Override
public ValidateResult validate(AuthorizationApplyDTO applyDTO) {
String json = applyDTO.getContractParams();
if (StringUtils.isEmpty(json)) {
throw new ApiException(ApiResultHelper.newParameterEmpty("contractParams字段不能為空"));
}
DataAuthContractParams params = Json.parseObject(json, DataAuthContractParams.class);
Map<String, String> validMap = ValidatorUtils.validate(params);
if (!validMap.isEmpty()) {
log.warn(validMap.toString());
throw new ApiException(ApiResultHelper.newBusinessError(lackFieldMessage(validMap.keySet().toArray(new String[0]))));
}
return new ValidateResult(true);
}
public static class DataAuthContractParams {
@NotEmpty
private String businessName;
@NotEmpty
private String dataProvider;
@NotEmpty
private String personalDataName;
@NotEmpty
private String dataDemander;
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public String getDataProvider() {
return dataProvider;
}
public void setDataProvider(String dataProvider) {
this.dataProvider = dataProvider;
}
public String getPersonalDataName() {
return personalDataName;
}
public void setPersonalDataName(String personalDataName) {
this.personalDataName = personalDataName;
}
public String getDataDemander() {
return dataDemander;
}
public void setDataDemander(String dataDemander) {
this.dataDemander = dataDemander;
}
}
@Test
public void test() {
AuthorizationApplyDTO applyDTO = new AuthorizationApplyDTO();
DataAuthContractParams params = new DataAuthContractParams();
params.setBusinessName("f");
params.setDataDemander("f");
params.setDataProvider("");
params.setPersonalDataName("");
applyDTO.setContractParams(Json.toJSONString(params));
ValidateResult result = new DataAuthValidator().validate(applyDTO);
System.out.println(Json.toJSONString(result));
assert result.isSeccess();
}
}運(yùn)行結(jié)果:
[main] WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {dataProvider=不能為空, personalDataName=不能為空}
com.fm.core.exceptions.ApiException: 參數(shù)contractParams中缺少字段:dataProvider, personalDataName
自定義校驗(yàn)規(guī)則(Validator)
自定義注解:
package com.fm.core.validation;
import com.fm.core.validation.validator.NotEmptyValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
/**
* Created by saleson on 2017/5/31.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Documented
@Constraint(validatedBy = {NotEmptyValidator.class})
public @interface NotEmpty {
String message() default "參數(shù)不能為null或空字符串";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}校驗(yàn)器(validator):
package com.fm.core.validation.validator;
import com.fm.core.validation.NotEmpty;
import com.fm.framework.utils.StringUtils;
import org.apache.commons.collections.MapUtils;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
/**
* Created by saleson on 2017/5/27.
*/
public class NotEmptyValidator extends AbstractValidator<NotEmpty, Object> {
@Override
protected boolean validNull(ConstraintValidatorContext context) {
return false;
}
@Override
protected boolean valid(Object value, ConstraintValidatorContext context) {
if (value instanceof String) {
return StringUtils.isNotEmpty(value.toString());
} else if (value instanceof Collection) {
return !org.springframework.util.CollectionUtils.isEmpty((Collection) value);
} else if (value instanceof Map) {
return MapUtils.isNotEmpty((Map) value);
} else if (value.getClass().isArray()) {
return Array.getLength(value) > 0;
}
return true;
}
}將上個(gè)demo中引用的org.hibernate.validator.constraints.NotEmpty改為com.fm.core.validation.NotEmpty即可。
運(yùn)行結(jié)果:
WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {dataProvider=參數(shù)不能為null或空字符串, personalDataName=參數(shù)不能為null或空字符串}
com.fm.core.exceptions.ApiException: 參數(shù)contractParams中缺少字段:dataProvider, personalDataName
級(jí)聯(lián)校驗(yàn)
校驗(yàn)的對(duì)象中包含另一個(gè)需要校驗(yàn)的對(duì)象時(shí),則可以使用@javax.validation.Valid
import com.fm.core.exceptions.ApiException;
import com.fm.core.validation.NotEmpty;
import com.fm.framework.api.ApiResultHelper;
import com.fm.framework.json.Json;
import com.fm.framework.utils.StringUtils;
import com.fm.grantauth.domain.ValidateResult;
import com.fm.grantauth.domain.dto.AuthorizationApplyDTO;
import com.fm.grantauth.utils.ValidatorUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.validation.Valid;
import java.util.Map;
/**
* Created by saleson on 2017/10/12.
*/
public class DataAuthValidator implements ContractParamsValidator {
private static final Logger log = LoggerFactory.getLogger(DataAuthValidator.class);
@Override
public ValidateResult validate(AuthorizationApplyDTO applyDTO) {
String json = applyDTO.getContractParams();
if (StringUtils.isEmpty(json)) {
throw new ApiException(ApiResultHelper.newParameterEmpty("contractParams字段不能為空"));
}
DataAuthContractParams params = Json.parseObject(json, DataAuthContractParams.class);
Map<String, String> validMap = ValidatorUtils.validate(params);
if (!validMap.isEmpty()) {
log.warn(validMap.toString());
throw new ApiException(ApiResultHelper.newBusinessError(lackFieldMessage(validMap.keySet().toArray(new String[0]))));
}
return new ValidateResult(true);
}
public static class DataAuthContractParams {
@NotEmpty
private String businessName;
@NotEmpty
private String dataProvider;
@NotEmpty
private String personalDataName;
@NotEmpty
private String dataDemander;
// @NotEmpty
@Valid
private Re r;
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public String getDataProvider() {
return dataProvider;
}
public void setDataProvider(String dataProvider) {
this.dataProvider = dataProvider;
}
public String getPersonalDataName() {
return personalDataName;
}
public void setPersonalDataName(String personalDataName) {
this.personalDataName = personalDataName;
}
public String getDataDemander() {
return dataDemander;
}
public void setDataDemander(String dataDemander) {
this.dataDemander = dataDemander;
}
public Re getR() {
return r;
}
public void setR(Re r) {
this.r = r;
}
}
public static class Re {
@NotEmpty
private String d;
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
}
@Test
public void test() {
AuthorizationApplyDTO applyDTO = new AuthorizationApplyDTO();
DataAuthContractParams params = new DataAuthContractParams();
params.setBusinessName("f");
params.setDataDemander("f");
params.setDataProvider("");
params.setPersonalDataName("");
Re r = new Re();
params.setR(r);
applyDTO.setContractParams(Json.toJSONString(params));
ValidateResult result = new DataAuthValidator().validate(applyDTO);
System.out.println(Json.toJSONString(result));
assert result.isSeccess();
}
}運(yùn)行結(jié)果:
WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {r.d=參數(shù)不能為null或空字符串, dataProvider=參數(shù)不能為null或空字符串, personalDataName=參數(shù)不能為null或空字符串}
com.fm.core.exceptions.ApiException: 參數(shù)contractParams中缺少字段:r.d, dataProvider, personalDataName
分組校驗(yàn)
對(duì)同一個(gè)Model,我們?cè)谠黾雍托薷臅r(shí)對(duì)參數(shù)的校驗(yàn)也是不一樣的,這個(gè)時(shí)候我們就需要定義分組驗(yàn)證。
com.fm.core.validation.NotEmpty#groups()就是用于分組校驗(yàn)的
添加兩個(gè)用于分組校驗(yàn)的接口:
public static interface GroupFirst {
}
public static interface GroupSecond {
}校驗(yàn)改成:
public static class DataAuthContractParams {
@NotEmpty
private String businessName;
@NotEmpty
private String dataProvider;
@NotEmpty(groups = GroupFirst.class)
private String personalDataName;
@NotEmpty(groups = {GroupFirst.class, GroupSecond.class})
private String dataDemander;
// @NotEmpty
@Valid
private Re r;
public String getBusinessName() {
return businessName;
}
public void setBusinessName(String businessName) {
this.businessName = businessName;
}
public String getDataProvider() {
return dataProvider;
}
public void setDataProvider(String dataProvider) {
this.dataProvider = dataProvider;
}
public String getPersonalDataName() {
return personalDataName;
}
public void setPersonalDataName(String personalDataName) {
this.personalDataName = personalDataName;
}
public String getDataDemander() {
return dataDemander;
}
public void setDataDemander(String dataDemander) {
this.dataDemander = dataDemander;
}
public Re getR() {
return r;
}
public void setR(Re r) {
this.r = r;
}
}
public static class Re {
@NotEmpty(groups = GroupSecond.class)
private String d;
public String getD() {
return d;
}
public void setD(String d) {
this.d = d;
}
}修改ValidatorUtils
package com.fm.grantauth.utils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Created by saleson on 2017/10/13.
*/
public class ValidatorUtils {
private static Validator validator = Validation.buildDefaultValidatorFactory()
.getValidator();
public static <T> Map<String, String> validate(T obj) {
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);
return convertErrorMap(set);
}
public static <T> Map<String, String> validate(T obj, Class<?>... groups) {
Set<ConstraintViolation<T>> set = validator.validate(obj, groups);
return convertErrorMap(set);
}
private static <T> Map<String, String> convertErrorMap(Set<ConstraintViolation<T>> set) {
Map<String, StringBuilder> errorMap = new HashMap<>();
if (set != null && set.size() > 0) {
String property = null;
for (ConstraintViolation<T> cv : set) {
//這里循環(huán)獲取錯(cuò)誤信息,可以自定義格式
property = cv.getPropertyPath().toString();
if (errorMap.get(property) != null) {
errorMap.get(property).append("," + cv.getMessage());
} else {
StringBuilder sb = new StringBuilder();
sb.append(cv.getMessage());
errorMap.put(property, sb);
}
}
}
return errorMap.entrySet().stream().collect(Collectors.toMap(k -> k.getKey(), v -> v.getValue().toString()));
}
}測(cè)試GroupFirst.class:
@Test
public void test() {
DataAuthContractParams params = new DataAuthContractParams();
params.setBusinessName("f");
params.setDataDemander("");
params.setDataProvider("f");
params.setPersonalDataName("");
Re r = new Re();
params.setR(r);
Map<String, String> validMap = ValidatorUtils.validate(params, GroupFirst.class);
System.out.println("error is: " + validMap);
}運(yùn)行結(jié)果:
error is: {dataDemander=參數(shù)不能為null或空字符串, personalDataName=參數(shù)不能為null或空字符串}
測(cè)試GroupSecond.class:
@Test
public void test() {
DataAuthContractParams params = new DataAuthContractParams();
params.setBusinessName("f");
params.setDataDemander("");
params.setDataProvider("f");
params.setPersonalDataName("");
Re r = new Re();
params.setR(r);
Map<String, String> validMap = ValidatorUtils.validate(params, GroupSecond.class);
System.out.println("error is: " + validMap);
}運(yùn)行結(jié)果:
error is: {dataDemander=參數(shù)不能為null或空字符串, r.d=參數(shù)不能為null或空字符串}
測(cè)試GroupFirst.class+GroupSecond.class:
@Test
public void test() {
DataAuthContractParams params = new DataAuthContractParams();
params.setBusinessName("f");
params.setDataDemander("");
params.setDataProvider("f");
params.setPersonalDataName("");
Re r = new Re();
params.setR(r);
Map<String, String> validMap = ValidatorUtils.validate(params, GroupFirst.class, GroupSecond.class);
System.out.println("error is: " + validMap);
}運(yùn)行結(jié)果:
error is: {dataDemander=參數(shù)不能為null或空字符串, r.d=參數(shù)不能為null或空字符串, personalDataName=參數(shù)不能為null或空字符串}
spring mvc上使用分組校驗(yàn):
@org.springframework.validation.annotation.Validated({GroupFirst.class, GroupSecond.class})總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Springboot項(xiàng)目javax.validation使用方法詳解
- java validation 后臺(tái)參數(shù)驗(yàn)證的使用詳解
- java使用Validation進(jìn)行數(shù)據(jù)校驗(yàn)的方式總結(jié)
- JAVA中通過(guò)Hibernate-Validation進(jìn)行參數(shù)驗(yàn)證
- 使用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)文章
java高并發(fā)下解決AtomicLong性能瓶頸方案LongAdder
這篇文章主要為大家介紹了java高并發(fā)下解決AtomicLong性能瓶頸方案LongAdder,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Java實(shí)戰(zhàn)之校園外賣(mài)點(diǎn)餐系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Java實(shí)現(xiàn)簡(jiǎn)易的校園外賣(mài)點(diǎn)餐系統(tǒng),文中采用的技術(shù)有:JSP、Spring、SpringMVC、MyBatis 等,感興趣的可以了解一下2022-03-03
學(xué)習(xí)在一臺(tái)新電腦上配置JAVA開(kāi)發(fā)環(huán)境
本文主要介紹了如何在一臺(tái)新電腦上配置JAVA開(kāi)發(fā)環(huán)境,每一個(gè)步驟都有對(duì)應(yīng)的截圖和文字說(shuō)明,需要的朋友可以參考下2015-07-07
Java實(shí)現(xiàn)茶葉售賣(mài)商城系統(tǒng)(java+SSM+JSP+EasyUi+mysql)
這篇文章主要介紹了基于SSM框架實(shí)現(xiàn)的一個(gè)茶葉售賣(mài)商城系統(tǒng),應(yīng)用到的技術(shù)有Jsp、SSM 、EasyUi,文中的示例代碼具有一定的學(xué)習(xí)價(jià)值,需要的朋友可以參考一下2021-12-12
Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢操作
Nebula?Graph?是一款開(kāi)源的、分布式的、易擴(kuò)展的原生圖數(shù)據(jù)庫(kù),能夠承載包含數(shù)千億個(gè)點(diǎn)和數(shù)萬(wàn)億條邊的超大規(guī)模數(shù)據(jù)集,并且提供毫秒級(jí)查詢,這篇文章主要介紹了Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢,需要的朋友可以參考下2022-10-10
Shiro在springboot中快速實(shí)現(xiàn)方法
Apache Shiro是一個(gè)Java的安全(權(quán)限)框架,可以容易的開(kāi)發(fā)出足夠好的應(yīng)用,既可以在JavaEE中使用,也可以在JavaSE中使用,這篇文章主要介紹了Shiro在springboot中快速實(shí)現(xiàn),需要的朋友可以參考下2023-02-02

