基于hibernate validator实现快速校验非法字符提示工具
非空校验注解器
IfNotNullRegex.java
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IfNotNullRegexConstraintValidator.class)
public @interface IfNotNullRegex {
String message() default "非法参数";
String[] regex();
boolean[] matcher();
String[] regexMsg() default "";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
自定义非空校验注解实现
IfNotNullRegexConstraintValidator.java
import com.google.common.collect.Lists;
import org.hibernate.validator.engine.ConstraintValidatorContextImpl;
import org.hibernate.validator.engine.PathImpl;
import org.springframework.util.ReflectionUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class IfNotNullRegexConstraintValidator implements
ConstraintValidator<IfNotNullRegex, String> {
private String[] regex;
private boolean[] matcher;
private String[] msg;
private LegalCharValidBuilder.LegalCharValid legalCharValid = LegalCharValidBuilder.instance().build();
@Override
public void initialize(IfNotNullRegex ifNotNull) {
regex = ifNotNull.regex();
msg = ifNotNull.regexMsg();
matcher = ifNotNull.matcher();
Assert.isTrue(regex.length == ifNotNull.matcher().length, "参数非法");
if (regex.length != ifNotNull.regexMsg().length) {
msg = new String[regex.length];
fillErrorMsg(ifNotNull.regexMsg(), ifNotNull.message());
}
}
@Override
public boolean isValid(String str, ConstraintValidatorContext constraintValidatorContext) {
if (StringUtil.isEmpty(str)) {
return true;
}
boolean flag;
List<String> errMsgList = Lists.newArrayList();
for (int i = 0; i < regex.length; i++) {
flag = str.matches(regex[i]);
flag = (flag == matcher[i]);
if (flag) {
constraintValidatorContext.disableDefaultConstraintViolation();
constraintValidatorContext.buildConstraintViolationWithTemplate(msg[i])
.addConstraintViolation();
errMsgList.add(msg[i]);
}
}
if (!CollectionUtils.isEmpty(errMsgList)) {
Map<Character, Set<Integer>> result = legalCharValid.findUnValidChar(str);
if (!CollectionUtils.isEmpty(result)) {
throw new UnLegalCheckException(errMsgList.get(0), errMsgList,
getProperties(constraintValidatorContext), result);
}
return false;
}
return true;
}
private void fillErrorMsg(String[] sourceArr, String defaultMsg) {
int sourlen = sourceArr.length;
for (int i = 0; i < msg.length; i++) {
if (i < sourlen) {
msg[i] = sourceArr[i];
} else {
msg[i] = defaultMsg;
}
}
}
private String getProperties(ConstraintValidatorContext constraintValidatorContext) {
try {
final String BASE_PATH_FIELD = "basePath";
Field field = ReflectionUtils.findField(ConstraintValidatorContextImpl.class,
BASE_PATH_FIELD);
field.setAccessible(true);
PathImpl path = (PathImpl) field.get(constraintValidatorContext);
return path.getLeafNode().asString();
} catch (Exception e) {
return "";
}
}
}
合法字符校验器
LegalCharValidBuilder.java
public class LegalCharValidBuilder {
private String baseLegalChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
private String extLegalChar = " /?:()_.,'+";
private boolean skipFirstCharValid = false;
public static LegalCharValidBuilder instance() {
return new LegalCharValidBuilder();
}
public LegalCharValid build() {
return new LegalCharValid(baseLegalChar, extLegalChar, skipFirstCharValid);
}
public LegalCharValidBuilder setBaseLegalChar(String baseLegalChar) {
this.baseLegalChar = baseLegalChar;
return this;
}
public LegalCharValidBuilder setExtLegalChar(String extLegalChar) {
this.extLegalChar = extLegalChar;
return this;
}
public LegalCharValidBuilder setSkipFirstCharValid(boolean skipFirstCharValid) {
this.skipFirstCharValid = skipFirstCharValid;
return this;
}
public class LegalCharValid {
private final String BASE_LEGAL_CHAR;
private final String TOTAL_LEGA_CHAR;
private final boolean SKIP_FIRST_CHAR_VALID;
private int binaryLegalCapacity = 2000;
private int[] LEGAL_ASCII_ARR;
LegalCharValid(String baseLegalChar, String extLegalChar, boolean skipFirstCharValid) {
BASE_LEGAL_CHAR = baseLegalChar;
TOTAL_LEGA_CHAR = baseLegalChar + extLegalChar;
SKIP_FIRST_CHAR_VALID = skipFirstCharValid;
LEGAL_ASCII_ARR = new int[TOTAL_LEGA_CHAR.length()];
char[] arr = TOTAL_LEGA_CHAR.toCharArray();
int i = 0;
for (char c : arr) {
LEGAL_ASCII_ARR[i++] = c;
}
Arrays.sort(LEGAL_ASCII_ARR);
}
public Map<Character, Set<Integer>> findUnValidChar(String str) {
Map<Character, Set<Integer>> unValid;
if (TOTAL_LEGA_CHAR.length() >= binaryLegalCapacity) {
unValid = findUnValidCharByBinarySearch(str);
} else {
unValid = findUnValidCharByNormal(str);
}
if (!SKIP_FIRST_CHAR_VALID && !validCharLegal(str.charAt(0))) {
char first = str.charAt(0);
Set<Integer> indexes = unValid.getOrDefault(first, Sets.newHashSet(0));
indexes.add(0);
unValid.put(first, indexes);
}
return unValid;
}
private boolean validCharLegal(char first) {
for (char legal : BASE_LEGAL_CHAR.toCharArray()) {
if (legal == first) {
return true;
}
}
return false;
}
public Map<Character, Set<Integer>> findUnValidCharByBinarySearch(String str) {
Map<Character, Set<Integer>> map = Maps.newHashMap();
if (StringUtil.isEmpty(str)) {
return map;
}
int i = 0;
for (char c : str.toCharArray()) {
int index = Arrays.binarySearch(LEGAL_ASCII_ARR, c);
if (index < 0) {
Set<Integer> indexes = map.getOrDefault(c, Sets.newHashSet(i));
indexes.add(i);
map.put(c, indexes);
}
i++;
}
return map;
}
public Map<Character, Set<Integer>> findUnValidCharByNormal(String str) {
Map<Character, Set<Integer>> map = Maps.newHashMap();
int i = 0;
char[] arr = str.toCharArray();
for (char c : arr) {
boolean find = false;
for (char s : TOTAL_LEGA_CHAR.toCharArray()) {
if (c == s) {
find = true;
break;
}
}
if (!find) {
Set<Integer> indexes = map.getOrDefault(c, Sets.newHashSet(i));
indexes.add(i);
map.put(c, indexes);
}
i++;
}
return map;
}
}
}
自定义非法字符异常
UnLegalCheckException.java
public class UnLegalCheckException extends RuntimeException {
private String errorCode;
private List<String> errorMsgs;
private Map<Character, Set<Integer>> unLegalMap;
private String checkField;
public UnLegalCheckException(String errorCode, String errorMsg, List<String> errorMsgs,
String field, Map<Character, Set<Integer>> map) {
super(errorMsg);
this.errorCode = errorCode;
this.errorMsgs = errorMsgs;
this.checkField = field;
this.unLegalMap = map;
}
public UnLegalCheckException(String errorMsg, List<String> errorMsgs, String field,
Map<Character, Set<Integer>> map) {
super(errorMsg);
this.checkField = field;
this.errorMsgs = errorMsgs;
this.unLegalMap = map;
}
public UnLegalCheckException(Throwable cause, String errorMsg, Map<Character, Set<Integer>> map) {
super(errorMsg, cause);
this.unLegalMap = map;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public Map<Character, Set<Integer>> getUnLegalMap() {
return unLegalMap;
}
public void setUnLegalMap(Map<Character, Set<Integer>> unLegalMap) {
this.unLegalMap = unLegalMap;
}
public String getCheckField() {
return checkField;
}
public void setCheckField(String checkField) {
this.checkField = checkField;
}
public List<String> getErrorMsgs() {
return errorMsgs;
}
public void setErrorMsgs(List<String> errorMsgs) {
this.errorMsgs = errorMsgs;
}
}
测试校验类
UserInfo.java
import lombok.Data;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
@Data
@ToString
public class UserInfo {
private static final long serialVersionUID = 7383672481338516001L;
@NotEmpty(message = "请填写姓名")
@IfNotNullRegex(regex = { ".*[\\u4E00-\\u9FA5\u3002\uFF1F\uFF01\uFF0C\u3001\uFF1B\uFF1A\u300C\u300D\u300E\u300F\u2018\u2019\u201C\u201D\uFF08\uFF09\u3014\u3015\u3010\u3011\u2014\u2026\u2013\uFF0E\u300A\u300B\u3008\u3009].*",
"^[a-zA-Z0-9/\\?:\\(\\)\\.\\,\\' \\+]*$",
"^[a-zA-Z0-9]{1}.*",
"\\d+"},
matcher = { true,false,false,true },
regexMsg = {"姓名不能xxx标点符号",
"姓名不xxx符号",
"姓名xxx符号",
"姓名xxx"})
private String name;
}
单元测试
unitTest.java
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import com.alibaba.fastjson.JSON;
import org.hibernate.validator.HibernateValidator;
public class UnitTest {
public static void main(String[] args){
UserInfo user = new UserInfo();
user.setName("haha@");
try{
createValidator(true).validate(user);
}catch(ValidationException e){
if(e.getCause() instanceof UnLegalCheckException){
UnLegalCheckException unLegal = (UnLegalCheckException) e.getCause();
System.out.println(JSON.toJSONString(unLegal));
System.out.println(JSON.toJSONString(unLegal.getErrorMsgs()));
}
}
}
private static Validator createValidator(boolean isFast) {
ValidatorFactory factory = Validation.byProvider(HibernateValidator.class).configure()
.failFast(isFast).buildValidatorFactory();
return factory.getValidator();
}
}