Merge branch 'pr_141' into dev
# Conflicts: # ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java2.X
commit
9ad354bf3a
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.dromara.common.core.constant;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.RegexPool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 常用正则表达式字符串
|
||||||
|
* <p>
|
||||||
|
* 常用正则表达式集合,更多正则见: https://any86.github.io/any-rule/
|
||||||
|
*
|
||||||
|
* @author Feng
|
||||||
|
*/
|
||||||
|
public interface RegexConstants extends RegexPool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
|
||||||
|
*/
|
||||||
|
public static final String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 身份证号码(后6位)
|
||||||
|
*/
|
||||||
|
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 = "^[1-9][0-9]\\d{4,9}$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮政编码
|
||||||
|
*/
|
||||||
|
public static final String POSTAL_CODE = "^[1-9]\\d{5}$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册账号
|
||||||
|
*/
|
||||||
|
public static final String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
|
||||||
|
*/
|
||||||
|
public static final String PASSWORD = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用状态(0表示正常,1表示停用)
|
||||||
|
*/
|
||||||
|
public static final String STATUS = "^[01]$";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正则表达式模式池工厂
|
||||||
|
* <p>初始化的时候将正则表达式加入缓存池当中</p>
|
||||||
|
* <p>提高正则表达式的性能,避免重复编译相同的正则表达式</p>
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,148 +0,0 @@
|
||||||
package org.dromara.common.core.utils;
|
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.core.convert.Convert;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
public class ReUtil {
|
|
||||||
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则中需要被转义的关键字
|
|
||||||
*/
|
|
||||||
public final static Set<Character> RE_KEYS = new HashSet<>(
|
|
||||||
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则替换指定值<br>
|
|
||||||
* 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* 例如:原字符串是:中文1234,我想把1234换成(1234),则可以:
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
|
|
||||||
*
|
|
||||||
* 结果:中文(1234)
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 正则替换指定值<br>
|
|
||||||
* 通过正则查找到字符串,然后把匹配到的字符串加入到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<String> 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 <T> 集合类型
|
|
||||||
* @param pattern 编译后的正则模式
|
|
||||||
* @param content 被查找的内容
|
|
||||||
* @param group 正则的分组
|
|
||||||
* @param collection 返回的集合类型
|
|
||||||
* @return 结果集
|
|
||||||
*/
|
|
||||||
public static <T extends Collection<String>> 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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 <T> CharSequence 的子类型
|
||||||
|
* @return 如果验证通过,返回输入的账号
|
||||||
|
* @throws ValidateException 如果验证失败
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> 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 <T> CharSequence 的子类型
|
||||||
|
* @return 如果验证通过,返回输入的状态
|
||||||
|
* @throws ValidateException 如果验证失败
|
||||||
|
*/
|
||||||
|
public static <T extends CharSequence> T validateStatus(T value, String errorMsg) throws ValidateException {
|
||||||
|
if (!isStatus(value)) {
|
||||||
|
throw new ValidateException(errorMsg);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,11 @@ package org.dromara.system.domain.bo;
|
||||||
|
|
||||||
import io.github.linpeilie.annotations.AutoMapper;
|
import io.github.linpeilie.annotations.AutoMapper;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
|
||||||
import jakarta.validation.constraints.Pattern;
|
import jakarta.validation.constraints.Pattern;
|
||||||
import jakarta.validation.constraints.Size;
|
import jakarta.validation.constraints.Size;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
import org.dromara.common.core.constant.RegexConstants;
|
||||||
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
import org.dromara.common.mybatis.core.domain.BaseEntity;
|
||||||
import org.dromara.system.domain.SysDictType;
|
import org.dromara.system.domain.SysDictType;
|
||||||
|
|
||||||
|
|
@ -38,7 +38,7 @@ public class SysDictTypeBo extends BaseEntity {
|
||||||
*/
|
*/
|
||||||
@NotBlank(message = "字典类型不能为空")
|
@NotBlank(message = "字典类型不能为空")
|
||||||
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符")
|
@Size(min = 0, max = 100, message = "字典类型类型长度不能超过{max}个字符")
|
||||||
@Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
|
@Pattern(regexp = RegexConstants.DICTIONARY_TYPE, message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
|
||||||
private String dictType;
|
private String dictType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue