基于hibernate validator实现快速校验非法字符提示工具

非空校验注解器

IfNotNullRegex.java

/*** 如果不为空的拦截验证*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IfNotNullRegexConstraintValidator.class)
public @interface IfNotNullRegex {/*** 默认错误文案* @return*/String message() default "非法参数";/*** 不为空场景下的正则* @return*/String[] regex();/*** 匹配结果为 matcher类型 显示对客文案* @return*/boolean[] matcher();/*** 正则提示的对客文案* @return*/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 implementsConstraintValidator<IfNotNullRegex, String> {/*** 正则表达式*/private String[]  regex;/*** 正则表达式匹配期望结果*/private boolean[] matcher;/*** 表达式对应的文案*/private String[]  msg;/*** 合法字符校验器*/private LegalCharValidBuilder.LegalCharValid legalCharValid = LegalCharValidBuilder.instance().build();@Overridepublic 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());}}@Overridepublic 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;}/*** 使用默认的错误文案填充正则对应的错误码* @param sourceArr* @param defaultMsg* @return*/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;}}}/*** 获取验证的字段* @param constraintValidatorContext* @return*/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;/*** 实例创建* @return*/public static LegalCharValidBuilder instance() {return new LegalCharValidBuilder();}/*** 构造器* @return*/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;/*** 合法的ascii数组集合(升序排序)*/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;}// 生成ascii 码 升序排序Arrays.sort(LEGAL_ASCII_ARR);}/*** 查找字符串中的非法字符* <pre>*   findUnValidCharByNormal("aha~") = {~=[3]}*   findUnValidCharByNormal("aha~,~") = {~=[3,5],,=[4]}* </pre>* @param str* @return*/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;}/*** 根据基础合法字符集校验字符是否合法* <pre>*     validCharLegal('.') = false*     validCharLegal('a') = true*     validCharLegal('0') = true* </pre>* @param first* @return*/private boolean validCharLegal(char first) {for (char legal : BASE_LEGAL_CHAR.toCharArray()) {if (legal == first) {return true;}}return false;}/*** 二分查找非法字符* <pre>*   findUnValidCharByNormal("aha~") = {~=[3]}*   findUnValidCharByNormal("aha~,~") = {~=[3,5],,=[4]}* </pre>* @param str* @return*/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);// 如果在合法字符库中未找到 就把当前的index下标放到map中if (index < 0) {Set<Integer> indexes = map.getOrDefault(c, Sets.newHashSet(i));indexes.add(i);map.put(c, indexes);}i++;}return map;}/*** 遍历查找非法字符* <pre>*   findUnValidCharByNormal("aha~") = {~=[3]}*   findUnValidCharByNormal("aha~,~") = {~=[3,5],,=[4]}* </pre>* @param str* @return*/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;/*** 构造函数* @param errorCode 错误码* @param errorMsg 错误消息* @param field 校验字段* @param map 非法字符*/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;}/*** 构造函数* @param errorMsg 错误消息* @param errorMsgs 错误消息集合(json)* @param field  校验字段* @param 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;}/*** 构造函数* @param cause 异常信息* @param errorMsg 错误消息* @param 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;
/*** 信息test*/
@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();}
}

快速校验非法字符工具相关推荐

  1. 开发工具 idea中出现Error:(1, 1) java: 非法字符: ‘\ufeff‘

    原因: ide 创建好文件后,发现类似于编码的问题,查看自己的编码发现 utf-8 没错 第一次: 先把 utf-8 转为 gbk ,之后再重新转回来.运行成功 第二次:再创建一个类,再运行时,又出现 ...

  2. python write非法字符报错_Python爬虫实现的微信公众号文章下载器

    平时爱逛知乎,收藏了不少别人推荐的数据分析.机器学习相关的微信公众号(这里就不列举了,以免硬广嫌疑).但是在手机微信上一页页的翻阅历史文章浏览,很不方便,电脑端微信也不方便. 所以我就想有什么方法能否 ...

  3. jetty 在请求URI里传入非法字符,jetty会断开连接,导致nginx认为该节点不健康

    为什么80%的码农都做不了架构师?>>>    jetty 在请求URI里传入非法字符(如直接一个16进制字节A1,非%A1,用抓包TCP工具发送),jetty抛出如下错误 8.1. ...

  4. maven项目在打war包时出现非法字符: '\ufeff' 解决方案

    http://blog.csdn.net/qi_fei/article/details/61416319 -------------------------------------------- 问题 ...

  5. long在C语言中是非法字符吗,C程序设计实践——实验指导

    一.课程的总体目标和具体要求 总体目标: 利用C语言和程序设计方法编制程序,借助计算机解决问题的基本能力.(支撑毕业能力要求1)独立解决文本处理.数学上的一些问题,编写较规范化的代码.(支撑毕业能力要 ...

  6. idea java 非法字符_IDEA提示非法字符,你不懂的UTF-8

    前些天用IDEA执行Java Web项目,提示非法字符,而且是一对一对的进行报错,由于涉及项目的保密,在这里之只能分享下排错的过程. 他报错会定位到某个java文件,在项目中看起来根本没什么问题,之后 ...

  7. 使用Visual Studio 部署SharePoint时提示“路径中具有非法字符”

    在使用VS 2012部署或发布SharePoint时,提示"路径中具有非法字符"(英文提示"Illegal characters in path"),找了半天, ...

  8. 快速提高网站排名工具大全

    快速提高网站排名工具大全 我试了一下,大部分可以登陆,想提高访问量的朋友可以去看看 中国论坛之家登陆入口http://www.vt123.com/link.html 商情168搜索引擎免费登陆入口ht ...

  9. Servlet过滤器(非法字符审核案例)

    1.过滤器 (1)什么是过滤器         servlet规范当中定义的一种特殊的组件,用来拦截容器的调用过程并进行相应的处理.     (2)如何写一个过滤器         step1,写一个 ...

最新文章

  1. Codeforces Round 263(Div. 2)
  2. css3宽度变大动画_学所 前端 | HTML5+CSS3
  3. PHP 实例 - AJAX RSS 阅读器
  4. mysql in优化_MySQL 探秘: 1 整体架构
  5. InnoDB的auto_increment指定值被重置问题
  6. 在线学ajax,ajax学习
  7. 10个CSS简写/优化技巧
  8. Mysql执行计划的extra列及filesort祥析
  9. CentOS6安装Cisco模拟器Dynamips
  10. Halcon 入门教程
  11. 02333软件工程_202010_试卷+答案
  12. 【无人机系统】四轴飞行器及其UAV飞控系统 - 桂林电子科技大学信息科技学院 电子工程系(四 五 )
  13. 非同帆响-得帆信息发布全新高生产力PaaS平台,重新定义企业软件生产力
  14. /项目3-分数类中的运算符重载
  15. 第四章 06 打印星号
  16. js 获取手机型号和版本
  17. 最简单的单例模式,Go版本的实现你写对了吗?
  18. Opencv2.4.9、VS2010配置及grabcut代码实例
  19. 程序员创业的方向选择
  20. putty 遂道_为什么将网络隧道称为“隧道”?

热门文章

  1. java里部分文件全选怎么整,全选和取消 怎么办
  2. C语言中关于强制类型转换问题
  3. 基于RK3399第一篇烧录Ubuntu18.04系统并实现PuTTy远程登录
  4. 实现SLIC算法生成像素画
  5. Android 更换开机logo和开机动画
  6. HDU 1415(Jugs)
  7. C++ 拓扑排序(AOV网络)
  8. 基于云桌面的外部设备重定向技术调研
  9. 《炒股的智慧》文摘1
  10. 我应该买Arduino还是Raspberry Pi?