diff --git a/flyfish-common/src/main/java/com/flyfish/framework/enums/BlankEnum.java b/flyfish-common/src/main/java/com/flyfish/framework/enums/BlankEnum.java new file mode 100644 index 0000000..abf80c2 --- /dev/null +++ b/flyfish-common/src/main/java/com/flyfish/framework/enums/BlankEnum.java @@ -0,0 +1,14 @@ +package com.flyfish.framework.enums; + +/** + * 空白的枚举 + * @author wangyu + */ +public enum BlankEnum implements NamedEnum { + NONE; + + @Override + public String getName() { + return "空"; + } +} diff --git a/flyfish-data/src/main/java/com/flyfish/framework/annotations/DictValue.java b/flyfish-data/src/main/java/com/flyfish/framework/annotations/DictValue.java new file mode 100644 index 0000000..4adf68c --- /dev/null +++ b/flyfish-data/src/main/java/com/flyfish/framework/annotations/DictValue.java @@ -0,0 +1,26 @@ +package com.flyfish.framework.annotations; + +import com.flyfish.framework.enums.BlankEnum; +import com.flyfish.framework.enums.NamedEnum; + +import java.lang.annotation.*; + +/** + * 字典值 + * + * @author wangyu + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@Documented +public @interface DictValue { + + // 字典值所属code + String value() default ""; + + // 使用枚举类标记 + Class enumType() default BlankEnum.class; + + // 中文名称 + String name() default ""; +} diff --git a/flyfish-dict/pom.xml b/flyfish-dict/pom.xml new file mode 100644 index 0000000..f00684a --- /dev/null +++ b/flyfish-dict/pom.xml @@ -0,0 +1,28 @@ + + + + flyfish-framework + com.flyfish.framework + 0.0.1-SNAPSHOT + + 4.0.0 + + flyfish-dict + 字典框架,集成字典解析,注解,服务,可自动注册和利用枚举反向注册 + + + 8 + 8 + + + + + com.flyfish.framework + flyfish-web + ${project.version} + true + + + diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/annotations/EnableDictProcess.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/annotations/EnableDictProcess.java new file mode 100644 index 0000000..9aa8706 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/annotations/EnableDictProcess.java @@ -0,0 +1,25 @@ +package com.flyfish.framework.dict.annotations; + +import com.flyfish.framework.dict.config.DictionaryConfig; +import org.springframework.context.annotation.Import; + +import java.lang.annotation.*; + +/** + * 开启字典处理逻辑 + * + * @author wangyu + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +@Import(DictionaryConfig.class) +public @interface EnableDictProcess { + + /** + * 扫描基本路径 + * + * @return 结果 + */ + String[] basePackages() default "com.flyfish.framework"; +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryConfig.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryConfig.java new file mode 100644 index 0000000..2cd5ae3 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryConfig.java @@ -0,0 +1,23 @@ +package com.flyfish.framework.dict.config; + +import com.flyfish.framework.dict.service.DictionaryService; +import org.springframework.context.annotation.Bean; + +/** + * 字典配置 + * + * @author wangyu + */ +public class DictionaryConfig { + + /** + * 注册字典处理器,开启类扫描注册 + * + * @param dictionaryService 字典服务 + * @return 结果 + */ + @Bean + public DictionaryProcessor dictionaryProcessor(DictionaryService dictionaryService) { + return new DictionaryProcessor(dictionaryService); + } +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryProcessor.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryProcessor.java new file mode 100644 index 0000000..036d0f9 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/config/DictionaryProcessor.java @@ -0,0 +1,102 @@ +package com.flyfish.framework.dict.config; + +import com.flyfish.framework.annotations.DictValue; +import com.flyfish.framework.dict.annotations.EnableDictProcess; +import com.flyfish.framework.dict.domain.Dictionary; +import com.flyfish.framework.dict.domain.DictionaryValue; +import com.flyfish.framework.dict.service.DictionaryService; +import com.flyfish.framework.enums.BlankEnum; +import com.flyfish.framework.enums.NamedEnum; +import com.flyfish.framework.utils.Assert; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.lang3.StringUtils; +import org.reflections.Reflections; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 字典处理器 + * + * @author wangyu + * 用于反向注册默认值 + */ +@RequiredArgsConstructor +public class DictionaryProcessor implements InitializingBean, ImportBeanDefinitionRegistrar { + + private final DictionaryService dictionaryService; + + private String[] basePackages; + + /** + * spring加载完成后,尝试注入值 + */ + @Override + public void afterPropertiesSet() { + Assert.notNull(basePackages, "未指定明确的字典扫描路径!"); + Reflections reflections = new Reflections(Stream.of(basePackages).collect(Collectors.toSet())); + Set fields = reflections.getFieldsAnnotatedWith(DictValue.class); + if (CollectionUtils.isNotEmpty(fields)) { + // 查找是否存在,不存在插入,存在无视 + List dictionaries = fields.stream().map(field -> field.getAnnotation(DictValue.class)) + .filter(annotation -> null != annotation && StringUtils.isNotBlank(annotation.value()) && + BlankEnum.class != annotation.enumType()) + .map(annotation -> dictionaryService + .getByCode(annotation.value()) + .map(dictionary -> { + if (CollectionUtils.isEmpty(dictionary.getValues())) { + dictionary.setValues(mapValues(annotation.enumType())); + } + return dictionary; + }) + .orElseGet(() -> { + Dictionary dictionary = new Dictionary(); + dictionary.setCode(annotation.value()); + dictionary.setValues(mapValues(annotation.enumType())); + dictionary.setName(StringUtils.isNotBlank(annotation.name()) ? annotation.name() : annotation.value()); + return dictionary; + })) + .distinct() + .collect(Collectors.toList()); + dictionaryService.updateBatch(dictionaries); + } + } + + /** + * 映射值,转换为字典表的值 + * + * @return 结果 + */ + private List mapValues(Class enumClass) { + return Arrays.stream(enumClass.getEnumConstants()).map(item -> { + DictionaryValue value = new DictionaryValue(); + value.setEnable(true); + value.setText(item.getName()); + value.setValue(((Enum) item).name()); + return value; + }).collect(Collectors.toList()); + } + + /** + * 注册bean定义,可以从这里取得元数据,自动加载bean + * + * @param metadata 元数据 + * @param registry 注册器 + */ + @Override + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { + Map attrs = metadata.getAnnotationAttributes(EnableDictProcess.class.getCanonicalName(), true); + this.basePackages = (String[]) MapUtils.getObject(attrs, "basePackages"); + } +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/controller/DictionaryController.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/controller/DictionaryController.java new file mode 100644 index 0000000..543d1ba --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/controller/DictionaryController.java @@ -0,0 +1,17 @@ +package com.flyfish.framework.dict.controller; + + +import com.flyfish.framework.beans.annotations.RestMapping; +import com.flyfish.framework.controller.BaseController; +import com.flyfish.framework.dict.domain.Dictionary; +import com.flyfish.framework.dict.domain.DictionaryQo; + +/** + * 字典表controller + * + * @author wangyu + */ +@RestMapping("dictionaries") +public class DictionaryController extends BaseController { + +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/Dictionary.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/Dictionary.java new file mode 100644 index 0000000..c736038 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/Dictionary.java @@ -0,0 +1,47 @@ +package com.flyfish.framework.dict.domain; + +import com.flyfish.framework.domain.base.AuditDomain; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.List; +import java.util.Objects; + +/** + * 字典表,包含字典值 + * + * @author wangyu + */ +@Getter +@Setter +@Document(collection = "dictionaries") +public class Dictionary extends AuditDomain { + + // 字典表的值 + private List values; + + // 字典描述 + private String description; + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Dictionary)) return false; + if (StringUtils.isBlank(code)) { + return super.equals(o); + } + Dictionary that = (Dictionary) o; + return StringUtils.equals(this.code, that.code); + } + + @Override + public int hashCode() { + if (StringUtils.isBlank(code)) { + return super.hashCode(); + } + return Objects.hash(getCode()); + } +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryQo.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryQo.java new file mode 100644 index 0000000..160c8cf --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryQo.java @@ -0,0 +1,15 @@ +package com.flyfish.framework.dict.domain; + +import com.flyfish.framework.domain.base.NameLikeQo; +import lombok.Getter; +import lombok.Setter; + +/** + * 字典查询实体 + * + * @author wangyu + */ +@Getter +@Setter +public class DictionaryQo extends NameLikeQo { +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryValue.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryValue.java new file mode 100644 index 0000000..966fcc0 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/domain/DictionaryValue.java @@ -0,0 +1,24 @@ +package com.flyfish.framework.dict.domain; + +import lombok.Data; + +/** + * 字典表的值 + * + * @author wangyu + */ +@Data +public class DictionaryValue { + + // 显示文字 + private String text; + + // 值 + private String value; + + // 描述 + private String description; + + // 是否启用 + private boolean enable; +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/repository/DictionaryRepository.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/repository/DictionaryRepository.java new file mode 100644 index 0000000..adc8350 --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/repository/DictionaryRepository.java @@ -0,0 +1,22 @@ +package com.flyfish.framework.dict.repository; + +import com.flyfish.framework.dict.domain.Dictionary; +import com.flyfish.framework.repository.DefaultRepository; + +import java.util.Optional; + +/** + * 字典的仓库 + * + * @author wangyu + */ +public interface DictionaryRepository extends DefaultRepository { + + /** + * 通过code查找 + * + * @param code 编码 + * @return 结果 + */ + Optional findByCode(String code); +} diff --git a/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java b/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java new file mode 100644 index 0000000..acbf0ae --- /dev/null +++ b/flyfish-dict/src/main/java/com/flyfish/framework/dict/service/DictionaryService.java @@ -0,0 +1,28 @@ +package com.flyfish.framework.dict.service; + + +import com.flyfish.framework.dict.domain.Dictionary; +import com.flyfish.framework.dict.repository.DictionaryRepository; +import com.flyfish.framework.service.impl.BaseServiceImpl; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +/** + * 字典表服务 + * + * @author wangyu + */ +@Service +public class DictionaryService extends BaseServiceImpl { + + /** + * 通过code查询 + * + * @return 结果 + */ + public Optional getByCode(String code) { + DictionaryRepository repository = this.getRepository(); + return repository.findByCode(code); + } +} diff --git a/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java index 8cb75ca..55b30c1 100644 --- a/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java +++ b/flyfish-web/src/main/java/com/flyfish/framework/beans/meta/BeanProperty.java @@ -1,5 +1,6 @@ package com.flyfish.framework.beans.meta; +import com.flyfish.framework.annotations.DictValue; import com.flyfish.framework.annotations.Property; import com.flyfish.framework.utils.StringFormats; import lombok.Data; @@ -73,6 +74,12 @@ public class BeanProperty { } Class clazz = descriptor.getPropertyType(); switch (property.getType()) { + case STRING: + // 如果字段使用DictValue注解,尝试使用字典值仓库 + if (null != field && field.isAnnotationPresent(DictValue.class)) { + DictValue dictValue = field.getAnnotation(DictValue.class); + property.prop("code", dictValue.value()); + } case LIST: // 尝试获取泛型参数,存在时,赋值子表单 if (null != field && field.isAnnotationPresent(SubBean.class)) { diff --git a/pom.xml b/pom.xml index 499abdb..08fd9a1 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,7 @@ flyfish-user flyfish-file flyfish-logging + flyfish-dict