When developing a business, it is inevitable to deal with some verification. If you write code like if-else to verify, there will be a large section of such code. Fortunately, there is a validation plug-in: javax.validation.validation-api, but the validation component of hibernate is generally referenced: org.hibernate.hibernate-validator, which already references the validation-api component.
Basic check type
JSR303 is a set of standards for JavaBean parameter verification. It defines many common verification annotations. We can directly add these annotations to the properties of our JavaBean, and then we can verify when we need to verify. The notes are as follows:
Hibernate validator extends the validation annotations based on JSR303. The extended annotations are as follows:
Write a DEMO to see
Validation tool class: 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) {
//这里循环获取错误信息,可以自定义格式
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();
}
}
operation result:
[main] WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {dataProvider=不能为空, personalDataName=不能为空}
com.fm.core.exceptions.ApiException: 参数contractParams中缺少字段:dataProvider, personalDataName
Custom Validation Rules (Validator)
Custom annotations:
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 "参数不能为null或空字符串";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
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;
}
}
Change the org.hibernate.validator.constraints.NotEmpty referenced in the previous demo to com.fm.core.validation.NotEmpty.
operation result:
WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {dataProvider=参数不能为null或空字符串, personalDataName=参数不能为null或空字符串}
com.fm.core.exceptions.ApiException: 参数contractParams中缺少字段:dataProvider, personalDataName
cascade check
When the verified object contains another object that needs to be verified, you can use @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();
}
}
operation result:
WARN com.fm.grantauth.module.authorization.contact.DataAuthValidator - {r.d=参数不能为null或空字符串, dataProvider=参数不能为null或空字符串, personalDataName=参数不能为null或空字符串}
com.fm.core.exceptions.ApiException: 参数contractParams中缺少字段:r.d, dataProvider, personalDataName
Packet check
For the same Model, we check the parameters differently when adding and modifying. At this time, we need to define group validation.
com.fm.core.validation.NotEmpty#groups() is used for group verification
Add two interfaces for packet verification:
public static interface GroupFirst {
}
public static interface GroupSecond {
}
Change the check to:
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;
}
}
Modify 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) {
//这里循环获取错误信息,可以自定义格式
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()));
}
}
Test 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);
}
Running result:
error is: {dataDemander=parameter cannot be null or empty string, personalDataName=parameter cannot be null or empty string}
Test 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);
}
Running result:
error is: {dataDemander=parameter cannot be null or empty string, rd=parameter cannot be null or empty string}
Test 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);
}
Running result:
error is: {dataDemander=parameter cannot be null or empty string, rd=parameter cannot be null or empty string, personalDataName=parameter cannot be null or empty string}
Use group validation on spring mvc: @org.springframework.validation.annotation.Validated({GroupFirst.class, GroupSecond.class})
Related Links Information
Spring4 New Features - Integrating Bean Validation 1.1 (JSR-349) to SpringMVC https://my.oschina.net/qjx1208/blog/200946
Java Bean Validation Best Practices http://www.cnblogs.com/ beiyan/p/5946345.html