枚举类型没有空的构造函数,没法在启动时用扫描器扫描注册成bean,没找到只扫描不注册的方法.
继承了ImportBeanDefinitionRegistrar,ClassPathBeanDefinitionScanner的自定义扫描器完成对自定义注解的扫描后就会注册bean,就报错了"Consider defining a bean of type 'java.lang.String' in your configuration",应该是因为枚举类型没有空的构造函数所致.
改为在启动后扫描class文件,读取值的方法,测试成功.
枚举定义:
@DictEnum(name = "DynamicDataTypeEnum")
@AllArgsConstructor
@Getter
public enum DynamicDataTypeEnum {
CurrentUser("1", "当前登录用户属性"),
Dict("2", "数据字典"),
Category("3", "分类字典"),
ApiAddress("4", "Api地址");
private String code;
private String name;
public Map toMap() {
Map<String, Object> map = new HashMap<>();
map.put("name", this.name);
map.put("code", this.code);
return map;
}
public static List<Map<String,Object>> toList(){
List<Map<String,Object>> list = new LinkedList<>();
list.add(CurrentUser.toMap());
list.add(Dict.toMap());
list.add(Category.toMap());
list.add(ApiAddress.toMap());
return list;
}
}
枚举中要有toList方法,以备使用
自定义注解:
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface DictEnum {
String name();
}
保存的缓存类:
public class DictEnumCache {
private static Dict enumNameCached = new Dict();
public static void put(String enumName, String className) {
enumNameCached.put(enumName, className);
}
public static String getClassName(String enumName) {
Object o = enumNameCached.get(enumName);
if (o != null) {
return o.toString();
}
return null;
}
public static Dict getAll(){
return enumNameCached;
}
}
扫描的类:
{
private ResourceLoader resourceLoader;
private ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
private static final String FULLTEXT_SACN_PACKAGE_PATH = "org.jeecg.modules";
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void run(String... args) throws Exception {
String concat = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
.concat(ClassUtils.convertClassNameToResourcePath(FULLTEXT_SACN_PACKAGE_PATH)
.concat("/**/*Enum*.class")); //只扫描文件名中包含Enum的文件,会快点
Resource[] resources = resolver.getResources(concat);
MetadataReader metadataReader = null;
for (Resource resource : resources) {
if (resource.isReadable()) {
metadataReader = metadataReaderFactory.getMetadataReader(resource);
String name = DictEnum.class.getName();
boolean dictEnum = metadataReader.getAnnotationMetadata().hasAnnotation(DictEnum.class.getName());
String className = metadataReader.getClassMetadata().getClassName();
if(dictEnum) {
Map<String, Object> annotationAttributes = metadataReader.getAnnotationMetadata()
.getAnnotationAttributes(DictEnum.class.getName());
String enumName = annotationAttributes.get("name").toString();
DictEnumCache.put(enumName,className);
}
}
}
}
}
控制器使用:
@RequestMapping(value = "/getDictItems/{dictCode}", method = RequestMethod.GET)
public Result<List<DictModel>> getDictItems(@PathVariable String dictCode, @RequestParam(value = "sign",required = false) String sign,HttpServletRequest request) {
log.info(" dictCode : "+ dictCode);
Result<List<DictModel>> result = new Result<List<DictModel>>();
List<DictModel> ls = null;
try {
if(dictCode.indexOf(",")!=-1) {
//关联表字典(举例:sys_user,realname,id)
String[] params = dictCode.split(",");
if(params.length<3) {
result.error500("字典Code格式不正确!");
return result;
}
//SQL注入校验(只限制非法串改数据库)
final String[] sqlInjCheck = {params[0],params[1],params[2]};
SqlInjectionUtil.filterContent(sqlInjCheck);
if(params.length==4) {
//SQL注入校验(查询条件SQL 特殊check,此方法仅供此处使用)
SqlInjectionUtil.specialFilterContent(params[3]);
ls = sysDictService.queryTableDictItemsByCodeAndFilter(params[0],params[1],params[2],params[3]);
}else if (params.length==3) {
ls = sysDictService.queryTableDictItemsByCode(params[0],params[1],params[2]);
}else{
result.error500("字典Code格式不正确!");
return result;
}
}else {
if(dictCode.indexOf(":")!=-1){
//格式 enum:DynamicDataTypeEnum
String[] split = dictCode.split(":");
String enumType = split[1];
String className = DictEnumCache.getClassName(enumType);
Class<?> aClass = Class.forName(className);
Method toList = aClass.getDeclaredMethod("toList");
Object[] oo = aClass.getEnumConstants();
List<Map<String,Object>> invoke = (List<Map<String,Object>>) toList.invoke(oo[0]);
List<DictModel> list = new LinkedList<>();
invoke.forEach(f->{
DictModel dictModel = new DictModel();
dictModel.setText(f.get("name").toString());
dictModel.setValue(f.get("code").toString());
list.add(dictModel);
});
ls = list;
}else {
//字典表
ls = sysDictService.queryDictItemsByCode(dictCode);
}
}
result.setSuccess(true);
result.setResult(ls);
log.info(result.toString());
} catch (Exception e) {
log.error(e.getMessage(),e);
result.error500("操作失败");
return result;
}
return result;
}
前端使用:
<j-dict-select-tag type="list" v-decorator="['valueType', validatorRules.valueType]"
:trigger-change="true" dictCode="enum:DynamicDataTypeEnum" placeholder="请选择值类型" />
向后端传参:enum:DynamicDataTypeEnum
本代码基于 jeecgboot 开源框架