diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java
index e4e7eb09..b13c0571 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/constant/RegexConstants.java
@@ -1,85 +1,49 @@
package org.dromara.common.core.constant;
+import cn.hutool.core.lang.RegexPool;
+
/**
- * 正则表达式
+ * 常用正则表达式字符串
+ *
+ * 常用正则表达式集合,更多正则见: https://any86.github.io/any-rule/
*
* @author Feng
*/
-public interface RegexConstants {
-
- /**
- * 中文字符正则表达式
- */
- public static final String CHINESE_REGEX = "[\\u4e00-\\u9fa5]+";
-
- /**
- * 姓名(2-4个中文字符正则)
- */
- public static final String NAME_REGEX = "^[\u4e00-\u9fa5]{2,4}$";
+public interface RegexConstants extends RegexPool {
/**
- * 匹配中国大陆手机号码
- */
- public static final String PHONE_NUMBER_REGEX = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
-
- /**
- * 座机号码
- */
- public static final String LANDLINE_REGEX = "^(0\\d{2,3})-?(\\d{7,8})$";
-
- /**
- * 电子邮箱
- */
- public static final String EMAIL_REGEX = "^[\\w+&*-]+(?:\\.[\\w+&*-]+)*@(?:[\\w+&*-]+\\.)+[a-zA-Z]{2,7}$";
-
- /**
- * 身份证号码(普通校验)
- */
- public static final String ID_CARD_REGEX_GENERAL = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)";
-
- /**
- * 身份证号码(精准校验 - 18位)
- */
- public static final String ID_CARD_REGEX_ACCURATE_18 = "^[1-9]\\d{5}(19|20)\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
-
- /**
- * 身份证号码(15位)
+ * 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
*/
- public static final String ID_CARD_REGEX_ACCURATE_15 = "^[1-9]\\d{5}\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{2}[0-9Xx]$";
+ public static final String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$";
/**
* 身份证号码(后6位)
*/
- public static final String ID_CARD_REGEX_LAST_6 = "^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
+ public static final String ID_CARD_LAST_6 = "^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
/**
* QQ号码
*/
- public static final String QQ_NUMBER_REGEX = "^[1-9][0-9]\\d{4,9}$";
+ public static final String QQ_NUMBER = "^[1-9][0-9]\\d{4,9}$";
/**
* 邮政编码
*/
- public static final String POSTAL_CODE_REGEX = "^[1-9]\\d{5}$";
+ public static final String POSTAL_CODE = "^[1-9]\\d{5}$";
/**
* 注册账号
*/
- public static final String ACCOUNT_REGEX = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";
+ public static final String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";
/**
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
*/
- public static final String PASSWORD_REGEX = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
+ public static final String PASSWORD = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
/**
* 通用状态(0表示正常,1表示停用)
*/
- public static final String STATUS_REGEX = "^[01]$";
-
- /**
- * 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
- */
- public static final String DICTIONARY_TYPE_REGEX = "^[a-z][a-z0-9_]*$";
+ public static final String STATUS = "^[01]$";
}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/factory/RegexPatternPoolFactory.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/factory/RegexPatternPoolFactory.java
new file mode 100644
index 00000000..fd907d2c
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/factory/RegexPatternPoolFactory.java
@@ -0,0 +1,52 @@
+package org.dromara.common.core.factory;
+
+import cn.hutool.core.lang.PatternPool;
+import org.dromara.common.core.constant.RegexConstants;
+
+import java.util.regex.Pattern;
+
+/**
+ * 正则表达式模式池工厂
+ *
初始化的时候将正则表达式加入缓存池当中
+ * 提高正则表达式的性能,避免重复编译相同的正则表达式
+ *
+ * @author 21001
+ */
+public class RegexPatternPoolFactory extends PatternPool {
+
+ /**
+ * 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
+ */
+ public static final Pattern DICTIONARY_TYPE = get(RegexConstants.DICTIONARY_TYPE);
+
+ /**
+ * 身份证号码(后6位)
+ */
+ public static final Pattern ID_CARD_LAST_6 = get(RegexConstants.ID_CARD_LAST_6);
+
+ /**
+ * QQ号码
+ */
+ public static final Pattern QQ_NUMBER = get(RegexConstants.QQ_NUMBER);
+
+ /**
+ * 邮政编码
+ */
+ public static final Pattern POSTAL_CODE = get(RegexConstants.POSTAL_CODE);
+
+ /**
+ * 注册账号
+ */
+ public static final Pattern ACCOUNT = get(RegexConstants.ACCOUNT);
+
+ /**
+ * 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
+ */
+ public static final Pattern PASSWORD = get(RegexConstants.PASSWORD);
+
+ /**
+ * 通用状态(0表示正常,1表示停用)
+ */
+ public static final Pattern STATUS = get(RegexConstants.STATUS);
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ReUtil.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ReUtil.java
deleted file mode 100644
index c9b673ab..00000000
--- a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/ReUtil.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package org.dromara.common.core.utils;
-
-
-import cn.hutool.core.convert.Convert;
-import org.dromara.common.core.constant.RegexConstants;
-import org.dromara.common.core.exception.ServiceException;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * 正则工具类
- *
- * @author Feng
- */
-public class ReUtil {
- public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
-
- /**
- * 正则中需要被转义的关键字
- */
- public final static Set RE_KEYS = new HashSet<>(Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));
-
- /**
- * 判断字符串是否匹配指定的正则表达式
- *
- * @param input 要检查的字符串
- * @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
- * @return 如果字符串与正则表达式匹配,返回 true;否则返回 false
- * @throws IllegalArgumentException 如果输入字符串或正则表达式为 null
- */
- public static boolean isValid(String input, String regex) {
- // 检查输入参数是否为null,如果是则抛出IllegalArgumentException
- if (StringUtils.isEmpty(input) || StringUtils.isEmpty(regex)) {
- throw new ServiceException("输入和正则表达式不得为空");
- }
- // 编译正则表达式
- Pattern pattern = Pattern.compile(regex);
- // 创建匹配器对象,并将输入字符串与正则表达式进行匹配
- Matcher matcher = pattern.matcher(input);
- // 返回匹配结果
- return matcher.matches();
- }
-
- /**
- * 从输入字符串中提取匹配的部分
- *
- * @param input 要提取的输入字符串
- * @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
- * @return 如果找到匹配的部分,则返回匹配的部分,否则返回原始输入字符串
- */
- public static String extractFromString(String input, String regex) {
- // 检查输入参数是否为null,如果是则抛出IllegalArgumentException
- if (StringUtils.isEmpty(input) || StringUtils.isEmpty(regex)) {
- throw new ServiceException("输入和正则表达式不得为空");
- }
- // 编译正则表达式
- Pattern pattern = Pattern.compile(regex);
- // 创建匹配器
- Matcher matcher = pattern.matcher(input);
- // 查找匹配
- if (matcher.find()) {
- // 获取匹配的部分
- return matcher.group(1);
- } else {
- // 如果没有匹配,返回原始字符串
- return input;
- }
- }
-
- /**
- * 从输入字符串中提取匹配的部分,如果没有匹配则返回默认值
- *
- * @param input 要提取的输入字符串
- * @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
- * @param defaultInput 如果没有匹配时返回的默认值
- * @return 如果找到匹配的部分,则返回匹配的部分,否则返回默认值
- */
- public static String extractFromString(String input, String regex, String defaultInput) {
- // 检查输入参数是否为null,如果是则抛出IllegalArgumentException
- if (StringUtils.isEmpty(input) || StringUtils.isEmpty(regex)) {
- throw new ServiceException("输入和正则表达式不得为空");
- }
- // 编译正则表达式
- Pattern pattern = Pattern.compile(regex);
- // 创建匹配器
- Matcher matcher = pattern.matcher(input);
- // 查找匹配
- if (matcher.find()) {
- // 获取匹配的部分
- return matcher.group(1);
- } else {
- // 如果没有匹配,返回默认值
- return defaultInput;
- }
- }
-
- /**
- * 正则替换指定值
- * 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
- *
- *
- * 例如:原字符串是:中文1234,我想把1234换成(1234),则可以:
- *
- *
- * ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
- *
- * 结果:中文(1234)
- *
- *
- * @param content 文本
- * @param regex 正则
- * @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容
- * @return 处理后的文本
- */
- public static String replaceAll(CharSequence content, String regex, String replacementTemplate) {
- final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
- return replaceAll(content, pattern, replacementTemplate);
- }
-
- /**
- * 正则替换指定值
- * 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
- *
- * @param content 文本
- * @param pattern {@link Pattern}
- * @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容
- * @return 处理后的文本
- * @since 3.0.4
- */
- public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) {
- if (StringUtils.isEmpty(content)) {
- return StringUtils.EMPTY;
- }
-
- final Matcher matcher = pattern.matcher(content);
- boolean result = matcher.find();
- if (result) {
- final Set varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>());
- final StringBuffer sb = new StringBuffer();
- do {
- String replacement = replacementTemplate;
- for (String var : varNums) {
- int group = Integer.parseInt(var);
- replacement = replacement.replace("$" + var, matcher.group(group));
- }
- matcher.appendReplacement(sb, escape(replacement));
- result = matcher.find();
- }
- while (result);
- matcher.appendTail(sb);
- return sb.toString();
- }
- return Convert.toStr(content);
- }
-
- /**
- * 取得内容中匹配的所有结果
- *
- * @param 集合类型
- * @param pattern 编译后的正则模式
- * @param content 被查找的内容
- * @param group 正则的分组
- * @param collection 返回的集合类型
- * @return 结果集
- */
- public static > T findAll(Pattern pattern, CharSequence content, int group,
- T collection) {
- if (null == pattern || null == content) {
- return null;
- }
-
- if (null == collection) {
- throw new NullPointerException("Null collection param provided!");
- }
-
- final Matcher matcher = pattern.matcher(content);
- while (matcher.find()) {
- collection.add(matcher.group(group));
- }
- return collection;
- }
-
- /**
- * 转义字符,将正则的关键字转义
- *
- * @param c 字符
- * @return 转义后的文本
- */
- public static String escape(char c) {
- final StringBuilder builder = new StringBuilder();
- if (RE_KEYS.contains(c)) {
- builder.append('\\');
- }
- builder.append(c);
- return builder.toString();
- }
-
- /**
- * 转义字符串,将正则的关键字转义
- *
- * @param content 文本
- * @return 转义后的文本
- */
- public static String escape(CharSequence content) {
- if (StringUtils.isBlank(content)) {
- return StringUtils.EMPTY;
- }
-
- final StringBuilder builder = new StringBuilder();
- int len = content.length();
- char current;
- for (int i = 0; i < len; i++) {
- current = content.charAt(i);
- if (RE_KEYS.contains(current)) {
- builder.append('\\');
- }
- builder.append(current);
- }
- return builder.toString();
- }
-
-}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java
new file mode 100644
index 00000000..b8b12d43
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexUtils.java
@@ -0,0 +1,30 @@
+package org.dromara.common.core.utils.regex;
+
+
+import cn.hutool.core.util.ReUtil;
+import org.dromara.common.core.constant.RegexConstants;
+
+/**
+ * 正则相关工具类
+ *
+ * @author Feng
+ */
+public final class RegexUtils extends ReUtil {
+
+ /**
+ * 从输入字符串中提取匹配的部分,如果没有匹配则返回默认值
+ *
+ * @param input 要提取的输入字符串
+ * @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
+ * @param defaultInput 如果没有匹配时返回的默认值
+ * @return 如果找到匹配的部分,则返回匹配的部分,否则返回默认值
+ */
+ public static String extractFromString(String input, String regex, String defaultInput) {
+ try {
+ return ReUtil.get(regex, input, 1);
+ } catch (Exception e) {
+ return defaultInput;
+ }
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexValidator.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexValidator.java
new file mode 100644
index 00000000..c0dda202
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/regex/RegexValidator.java
@@ -0,0 +1,105 @@
+package org.dromara.common.core.utils.regex;
+
+import cn.hutool.core.exceptions.ValidateException;
+import cn.hutool.core.lang.Validator;
+import org.dromara.common.core.factory.RegexPatternPoolFactory;
+
+import java.util.regex.Pattern;
+
+/**
+ * 正则字段校验器
+ * 主要验证字段非空、是否为满足指定格式等
+ *
+ * @author Feng
+ */
+public class RegexValidator extends Validator {
+
+ /**
+ * 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
+ */
+ public static final Pattern DICTIONARY_TYPE = RegexPatternPoolFactory.DICTIONARY_TYPE;
+
+ /**
+ * 身份证号码(后6位)
+ */
+ public static final Pattern ID_CARD_LAST_6 = RegexPatternPoolFactory.ID_CARD_LAST_6;
+
+ /**
+ * QQ号码
+ */
+ public static final Pattern QQ_NUMBER = RegexPatternPoolFactory.QQ_NUMBER;
+
+ /**
+ * 邮政编码
+ */
+ public static final Pattern POSTAL_CODE = RegexPatternPoolFactory.POSTAL_CODE;
+
+ /**
+ * 注册账号
+ */
+ public static final Pattern ACCOUNT = RegexPatternPoolFactory.ACCOUNT;
+
+ /**
+ * 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
+ */
+ public static final Pattern PASSWORD = RegexPatternPoolFactory.PASSWORD;
+
+ /**
+ * 通用状态(0表示正常,1表示停用)
+ */
+ public static final Pattern STATUS = RegexPatternPoolFactory.STATUS;
+
+
+ /**
+ * 检查输入的账号是否匹配预定义的规则
+ *
+ * @param value 要验证的账号
+ * @return 如果账号符合规则,返回 true;否则,返回 false。
+ */
+ public static boolean isAccount(CharSequence value) {
+ return isMatchRegex(ACCOUNT, value);
+ }
+
+ /**
+ * 验证输入的账号是否符合规则,如果不符合,则抛出 ValidateException 异常
+ *
+ * @param value 要验证的账号
+ * @param errorMsg 验证失败时抛出的异常消息
+ * @param CharSequence 的子类型
+ * @return 如果验证通过,返回输入的账号
+ * @throws ValidateException 如果验证失败
+ */
+ public static T validateAccount(T value, String errorMsg) throws ValidateException {
+ if (!isAccount(value)) {
+ throw new ValidateException(errorMsg);
+ }
+ return value;
+ }
+
+ /**
+ * 检查输入的状态是否匹配预定义的规则
+ *
+ * @param value 要验证的状态
+ * @return 如果状态符合规则,返回 true;否则,返回 false。
+ */
+ public static boolean isStatus(CharSequence value) {
+ return isMatchRegex(STATUS, value);
+ }
+
+ /**
+ * 验证输入的状态是否符合规则,如果不符合,则抛出 ValidateException 异常
+ *
+ * @param value 要验证的状态
+ * @param errorMsg 验证失败时抛出的异常消息
+ * @param CharSequence 的子类型
+ * @return 如果验证通过,返回输入的状态
+ * @throws ValidateException 如果验证失败
+ */
+ public static T validateStatus(T value, String errorMsg) throws ValidateException {
+ if (!isStatus(value)) {
+ throw new ValidateException(errorMsg);
+ }
+ return value;
+ }
+
+}
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java
index e3336936..18a1979f 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java
@@ -42,7 +42,7 @@ public class SysDictTypeBo extends BaseEntity {
*/
@NotBlank(message = "字典类型不能为空", groups = { AddGroup.class, EditGroup.class })
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符")
- @Pattern(regexp = RegexConstants.DICTIONARY_TYPE_REGEX, message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
+ @Pattern(regexp = RegexConstants.DICTIONARY_TYPE, message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
private String dictType;
/**