fix 修复 一些发现的小bug
- 短信验证码限流 key 改为 #phoneNumber,验证码改为发送成功后再写 Redis,失败消息避免 NPE - 邮箱验证码改为邮件发送成功后再写 Redis - ValidatorUtils 增加 NPE 校验 - 部门导入路径不存在时明确报错,不再静默转成 null - 重复提交切面完整扫描数组、集合、Map 中的过滤对象 - Excel 级联下拉补齐一级选项的 Excel 名称规则校验和重复校验
This commit is contained in:
+3
@@ -26,6 +26,9 @@ public class ValidatorUtils {
|
||||
* @throws ConstraintViolationException 如果校验不通过,则抛出参数校验异常
|
||||
*/
|
||||
public static <T> void validate(T object, Class<?>... groups) {
|
||||
if (object == null) {
|
||||
throw new RuntimeException("请求参数不能为空");
|
||||
}
|
||||
Set<ConstraintViolation<T>> validate = VALID.validate(object, groups);
|
||||
if (!validate.isEmpty()) {
|
||||
throw new ConstraintViolationException("参数校验异常", validate);
|
||||
|
||||
+25
-4
@@ -51,6 +51,9 @@ public class DropDownOptions {
|
||||
* 分隔符
|
||||
*/
|
||||
private static final String DELIMITER = "_";
|
||||
private static final String OPTION_PART_REGEX = "^[A-Za-z0-9\\u4e00-\\u9fa5]+$";
|
||||
private static final String EXCEL_NAME_REGEX = "^[A-Za-z_\\u4e00-\\u9fa5][A-Za-z0-9_\\u4e00-\\u9fa5]*$";
|
||||
private static final String CELL_REFERENCE_REGEX = "^[A-Za-z]{1,3}[1-9][0-9]*$";
|
||||
|
||||
/**
|
||||
* 创建只有一级的下拉选
|
||||
@@ -69,10 +72,9 @@ public class DropDownOptions {
|
||||
*/
|
||||
public static String createOptionValue(Object... vars) {
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
String regex = "^[\\S\\d\\u4e00-\\u9fa5]+$";
|
||||
for (int i = 0; i < vars.length; i++) {
|
||||
String var = StrUtil.trimToEmpty(Convert.toStr(vars[i]));
|
||||
if (!var.matches(regex)) {
|
||||
if (!var.matches(OPTION_PART_REGEX)) {
|
||||
throw new ServiceException("选项数据不符合规则,仅允许使用中英文字符以及数字");
|
||||
}
|
||||
stringBuffer.append(var);
|
||||
@@ -81,10 +83,29 @@ public class DropDownOptions {
|
||||
stringBuffer.append(DELIMITER);
|
||||
}
|
||||
}
|
||||
if (stringBuffer.toString().matches("^\\d_*$")) {
|
||||
String optionValue = stringBuffer.toString();
|
||||
validateOptionValue(optionValue);
|
||||
return optionValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验级联下拉选项值是否可作为 Excel 名称管理器名称。
|
||||
*
|
||||
* @param optionValue 选项值
|
||||
*/
|
||||
public static void validateOptionValue(String optionValue) {
|
||||
if (StrUtil.isBlank(optionValue)) {
|
||||
throw new ServiceException("选项数据不能为空");
|
||||
}
|
||||
if (optionValue.matches("^[0-9].*")) {
|
||||
throw new ServiceException("禁止以数字开头");
|
||||
}
|
||||
return stringBuffer.toString();
|
||||
if (!optionValue.matches(EXCEL_NAME_REGEX)) {
|
||||
throw new ServiceException("选项数据不符合Excel名称规则,仅允许中英文、数字或下划线,且不能以数字开头");
|
||||
}
|
||||
if (optionValue.matches(CELL_REFERENCE_REGEX)) {
|
||||
throw new ServiceException("选项数据不能为Excel单元格引用");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+14
@@ -202,6 +202,7 @@ public class ExcelDownHandler implements SheetWriteHandler {
|
||||
if (CollUtil.isEmpty(firstOptions)) {
|
||||
return;
|
||||
}
|
||||
validateLinkedOptionNames(firstOptions);
|
||||
Map<String, List<String>> secoundOptionsMap = new HashMap<>();
|
||||
options.getNextOptions().forEach((k, v) -> secoundOptionsMap.put(k, new ArrayList<>(v)));
|
||||
|
||||
@@ -313,6 +314,19 @@ public class ExcelDownHandler implements SheetWriteHandler {
|
||||
currentLinkedOptionsSheetIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验级联下拉一级选项可作为 Excel 名称,且不能重复。
|
||||
*/
|
||||
private void validateLinkedOptionNames(List<String> firstOptions) {
|
||||
Set<String> names = new HashSet<>();
|
||||
for (String firstOption : firstOptions) {
|
||||
DropDownOptions.validateOptionValue(firstOption);
|
||||
if (!names.add(firstOption)) {
|
||||
throw new ServiceException("级联下拉一级选项重复:" + firstOption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <h2>额外表格形式的普通下拉框</h2>
|
||||
* 由于下拉框可选值数量过多,为提升Excel打开效率,使用额外表格形式做下拉
|
||||
|
||||
+18
-3
@@ -24,6 +24,7 @@ import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -150,16 +151,30 @@ public class RepeatSubmitAspect {
|
||||
public boolean isFilterObject(final Object o) {
|
||||
Class<?> clazz = o.getClass();
|
||||
if (clazz.isArray()) {
|
||||
return MultipartFile.class.isAssignableFrom(clazz.getComponentType());
|
||||
if (MultipartFile.class.isAssignableFrom(clazz.getComponentType())) {
|
||||
return true;
|
||||
}
|
||||
int length = Array.getLength(o);
|
||||
for (int i = 0; i < length; i++) {
|
||||
Object value = Array.get(o, i);
|
||||
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else if (Collection.class.isAssignableFrom(clazz)) {
|
||||
Collection collection = (Collection) o;
|
||||
for (Object value : collection) {
|
||||
return value instanceof MultipartFile;
|
||||
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (Map.class.isAssignableFrom(clazz)) {
|
||||
Map map = (Map) o;
|
||||
for (Object value : map.values()) {
|
||||
return value instanceof MultipartFile;
|
||||
if (ObjectUtil.isNotNull(value) && isFilterObject(value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
|
||||
|
||||
Reference in New Issue
Block a user