1、新增InDict注解校验字典;2、标签模板、标签入参type支持InDict=labelType检查;

This commit is contained in:
gaoqr
2026-08-06 10:50:50 +08:00
parent 1c9a8bd42e
commit 9adbf11a49
9 changed files with 107 additions and 5 deletions
@@ -3,6 +3,7 @@ package com.cf.imes.framework.dict.core.util;
import cn.hutool.core.lang.Pair; import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.util.cache.CacheUtils; import com.cf.imes.framework.common.util.cache.CacheUtils;
import com.cf.imes.framework.common.enums.CommonStatusEnum;
import com.cf.imes.module.system.api.dict.DictDataApi; import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO; import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@@ -102,4 +103,19 @@ public class DictFrameworkUtils {
return PARSE_DICT_DATA_CACHE.get(new Pair<>(dictType, label)).getValue(); return PARSE_DICT_DATA_CACHE.get(new Pair<>(dictType, label)).getValue();
} }
/**
* 判断指定字典值是否存在且已启用。
*
* @param dictType 字典类型
* @param value 字典值
* @return 是否为有效字典值
*/
@SneakyThrows
public static boolean isDictDataValid(String dictType, String value) {
DictDataRespDTO dictData = GET_DICT_DATA_CACHE.get(new Pair<>(dictType, value));
return dictData != DICT_DATA_NULL
&& dictData.getValue() != null
&& CommonStatusEnum.ENABLE.getStatus().equals(dictData.getStatus());
}
} }
@@ -0,0 +1,32 @@
package com.cf.imes.framework.dict.core.validation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 校验字段值是否为指定类型下存在且启用的字典值。
*/
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = InDictValidator.class)
public @interface InDict {
/**
* 字典类型。
*/
String value();
String message() default "inDict.message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@@ -0,0 +1,43 @@
package com.cf.imes.framework.dict.core.validation;
import com.cf.imes.framework.common.constants.ResourceBundleConstants;
import com.cf.imes.framework.common.util.i18n.core.util.ResourceBundleUtils;
import com.cf.imes.framework.dict.core.util.DictFrameworkUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.Locale;
/**
* 字典值校验器。
*/
public class InDictValidator implements ConstraintValidator<InDict, Object> {
private String dictType;
@Override
public void initialize(InDict annotation) {
this.dictType = annotation.value();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
// 是否必填由 @NotNull、@NotBlank 等注解负责。
if (value == null) {
return true;
}
if (DictFrameworkUtils.isDictDataValid(dictType, String.valueOf(value))) {
return true;
}
String messageKey = context.getDefaultConstraintMessageTemplate();
Locale locale = LocaleContextHolder.getLocale();
String message = ResourceBundleUtils.getMessage(
ResourceBundleConstants.MESSAGE_ENUM_PATH, messageKey, messageKey, locale, value);
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
return false;
}
}
@@ -32,4 +32,6 @@ public class DictTypeConstants {
public static final String PLATE_TEXTURE_TYPE = "plate_texture_type";// 板材纹路:0有 1无 public static final String PLATE_TEXTURE_TYPE = "plate_texture_type";// 板材纹路:0有 1无
public static final String LABEL_TYPE = "labelType"; // 标签类型
} }
@@ -1,5 +1,7 @@
package com.cf.imes.module.system.controller.admin.label.vo; package com.cf.imes.module.system.controller.admin.label.vo;
import com.cf.imes.framework.dict.core.validation.InDict;
import com.cf.imes.module.system.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
@@ -17,6 +19,7 @@ public class LabelSaveReqVO {
@Schema(description = "标签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "标签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "标签类型不能为空") @NotNull(message = "标签类型不能为空")
@Size(max = 32, message = "标签类型长度不能超过32个字符") @Size(max = 32, message = "标签类型长度不能超过32个字符")
@InDict(DictTypeConstants.LABEL_TYPE)
private String type; private String type;
@Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@@ -1,5 +1,7 @@
package com.cf.imes.module.system.controller.admin.labeltemplate.vo; package com.cf.imes.module.system.controller.admin.labeltemplate.vo;
import com.cf.imes.framework.dict.core.validation.InDict;
import com.cf.imes.module.system.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
@@ -16,6 +18,7 @@ public class LabelTemplateSaveReqVO {
@Schema(description = "标签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @Schema(description = "标签类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "标签类型不能为空") @NotNull(message = "标签类型不能为空")
@Size(max = 50, message = "标签类型长度不能超过50个字符") @Size(max = 50, message = "标签类型长度不能超过50个字符")
@InDict(DictTypeConstants.LABEL_TYPE)
private String type; private String type;
@Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") @Schema(description = "标签名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五")
@@ -1,4 +1,5 @@
inEnum.message=必須在指定範圍 {0} inEnum.message=必須在指定範圍 {0}
inDict.message=字典值 {0} 不存在或已停用
inScope.message={0}不合法 inScope.message={0}不合法
inScope.adPosition=廣告位置 inScope.adPosition=廣告位置
@@ -1,4 +1,5 @@
inEnum.message=Must be within the specified range {0} inEnum.message=Must be within the specified range {0}
inDict.message=Dictionary value {0} does not exist or is disabled
inScope.message={0} is illegal inScope.message={0} is illegal
inScope.adPosition=Advertising position inScope.adPosition=Advertising position
@@ -1,4 +1,5 @@
inEnum.message=必须在指定范围 {0} inEnum.message=必须在指定范围 {0}
inDict.message=字典值 {0} 不存在或已停用
inScope.message={0}不合法 inScope.message={0}不合法
inScope.adPosition=广告位置 inScope.adPosition=广告位置