枚举字典管理器

15 篇文章 1 订阅
6 篇文章 0 订阅

后端通常需要为了不使用魔法值而去定义枚举类,而枚举类又经常需要被当做数据字典传给前端。次套解决方案就是为了解决枚举值的统一管理的问题,枚举类只要实现 EnumService接口,就可以集成这套方案。

EnumDictionary - 数据字典对象

import java.io.Serializable;

/**
 * 数据字典
 *
 * @author: Neo
 * @date: 2020/12/31 15:59
 * @version: 1.0
 */
public class EnumDictionary implements Serializable {
    private static final long serialVersionUID = -1113764940965416458L;

    private Integer code;

    private String name;

    private String message;

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

BaseEnum - 枚举接口

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author: Neo
 * @date: 2020/12/21 11:09
 * @version: 1.0
 */
public interface BaseEnum {

    String CODE = "code";

    String MESSAGE = "message";

    String ENUM_CLASS_TAIL = "Enum";

    String DEFAULT_SEPARATOR = ",";

    /**
     * 编码
     *
     * @return
     */
    Integer getCode();

    /**
     * 详情
     *
     * @return
     */
    String getMessage();

    /**
     * 是否需要以字典的形式被加载,默认:false
     *
     * @return
     */
    default boolean isLoadDictionary() {
        return false;
    }

    /**
     * 字典名称
     *
     * @return
     */
    default String dictionaryName() {
        return this.getClass().getSimpleName();
    }


    /**
     * 是否使用默认方式生成字典,默认:false
     *
     * @return
     */
    default boolean isDefaultAssembly() {
        return false;
    }

    /**
     * 自定义字典数据
     *
     * @return
     */
    default List<EnumDictionary> dictionaries() {
        return Collections.EMPTY_LIST;
    }

    /**
     * 当前对象的 code 是否 和参数中的 code 相等
     *
     * @param code
     * @return
     */
    default boolean equalsCode(Integer code) {
        return Objects.equals(this.getCode(), code);
    }

    /**
     * 当前对象是否和已知对象不等
     *
     * @param e
     * @return
     */
    default boolean notEquals(BaseEnum e) {
        return this != e;
    }


    // =================================【上为接口】=================================
    // ============================================================================
    // =================================【下为方法】=================================


    /**
     * 通过 code 获取指定 枚举类型中的 枚举对象
     *
     * @param clazz
     * @param code
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> T getByCode(Class<T> clazz, Integer code) {
        if (Objects.isNull(clazz) || Objects.isNull(code)) {
            return null;
        }
        for (T e : clazz.getEnumConstants()) {
            if (e.equalsCode(code)) {
                return e;
            }
        }
        return null;
    }

    /**
     * 通过 code 获取指定 枚举类型中的 detail
     *
     * @param enumClass
     * @param code
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> String getMessageByCode(Class<T> enumClass, Integer code) {
        BaseEnum e = getByCode(enumClass, code);
        if (null == e) {
            return null;
        }
        return e.getMessage();
    }

    /**
     * 枚举 转 List
     *
     * @param enums
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> List<Map<String, String>> toList(T[] enums) {
        if (ArrayUtils.isEmpty(enums)) {
            return Collections.EMPTY_LIST;
        }
        List<Map<String, String>> result = new ArrayList<>(enums.length);
        Map<String, String> map;
        for (T e : enums) {
            map = new HashMap<>(2);
            map.put(CODE, String.valueOf(e.getCode()));
            map.put(MESSAGE, e.getMessage());
            result.add(map);
        }
        return result;
    }


    /**
     * 枚举 转 Map
     *
     * @param enums
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> Map<Integer, String> toMap(T[] enums) {
        if (ArrayUtils.isEmpty(enums)) {
            return Collections.EMPTY_MAP;
        }
        Map<Integer, String> result = new HashMap<>(enums.length);
        for (T e : enums) {
            result.put(e.getCode(), e.getMessage());
        }
        return result;
    }

    /**
     * 转枚举 Map
     *
     * @param enums
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> Map<Integer, T> toEnumMap(T[] enums) {
        if (ArrayUtils.isEmpty(enums)) {
            return Collections.EMPTY_MAP;
        }
        Map<Integer, T> result = new HashMap<>(enums.length);
        for (T e : enums) {
            result.put(e.getCode(), e);
        }
        return result;
    }

    /**
     * 枚举转字典集合
     *
     * @param enums
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> List<EnumDictionary> toDictionaries(T[] enums) {
        if (ArrayUtils.isEmpty(enums)) {
            return Collections.EMPTY_LIST;
        }
        List<EnumDictionary> result = new ArrayList<>(enums.length);
        for (T e : enums) {
            result.add(toDictionary(e));
        }
        return result;
    }

    /**
     * 枚举转字典
     *
     * @param e
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> EnumDictionary toDictionary(T e) {
        if (Objects.isNull(e)) {
            return null;
        }
        EnumDictionary result = new EnumDictionary();
        result.setCode(e.getCode());
        result.setName(e.toString());
        result.setMessage(e.getMessage());
        return result;
    }


    /**
     * 清除枚举类尾巴
     *
     * @param clazz
     * @return
     */
    static String clearEnumClassTail(Class<?> clazz) {
        return Objects.isNull(clazz) ? StringUtils.EMPTY : clearEnumClassTail(clazz.getSimpleName());
    }

    /**
     * 清除枚举类尾巴
     *
     * @param className
     * @return
     */
    static String clearEnumClassTail(String className) {
        return StringUtils.removeEndIgnoreCase(className, ENUM_CLASS_TAIL);
    }


    /**
     * 通过 code 获取实例
     *
     * @param map
     * @param code
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> T of(Map<Integer, T> map, Integer code) {
        if (MapUtils.isEmpty(map) || Objects.isNull(code)) {
            return null;
        }
        return map.get(code);
    }

    /**
     * 通过 code 获取详情
     *
     * @param map
     * @param code
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> String getMessageByCode(Map<Integer, T> map, Integer code) {
        T t = of(map, code);
        return Objects.nonNull(t) ? t.getMessage() : StringUtils.EMPTY;
    }

    /**
     * 通过 codes 批量获取详情
     *
     * @param map
     * @param codes
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> String getMessagesByCodes(Map<Integer, T> map, String codes) {
        return getMessagesByCodes(map, codes, DEFAULT_SEPARATOR);
    }

    /**
     * 通过 codes 批量获取详情
     *
     * @param map
     * @param codes
     * @param separator
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> String getMessagesByCodes(Map<Integer, T> map, String codes, String separator) {
        if (StringUtils.isBlank(codes) || Objects.isNull(separator)) {
            return StringUtils.EMPTY;
        }
        List<String> codeList = Splitter.on(separator).trimResults().omitEmptyStrings().splitToList(codes);
        return getMessagesByCodes(map, codeList);
    }

    /**
     * 通过 codes 批量获取详情
     *
     * @param map
     * @param codes
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> String getMessagesByCodes(Map<Integer, T> map, List<String> codes) {
        return Joiner.on(DEFAULT_SEPARATOR).join(getMessageListByCodes(map, codes));
    }


    /**
     * 通过 codes 批量获取详情
     *
     * @param map
     * @param codes
     * @param <T>
     * @return
     */
    static <T extends BaseEnum> List<String> getMessageListByCodes(Map<Integer, T> map, List<String> codes) {
        if (CollectionUtils.isEmpty(codes)) {
            return Collections.EMPTY_LIST;
        }

        List<String> result = new ArrayList<>(CollectionUtils.size(codes));
        for (String code : codes) {
            result.add(getMessageByCode(map, Integer.valueOf(code)));
        }
        return result;
    }
}

枚举类使用示例:YesOrNoEnum

import com.ceair.shoppingservice.base.eunms.BaseEnum;

import java.util.Objects;

/**
 * 是否枚举
 * 
 * @author: Neo
 * @date: 2021/1/7 14:56
 * @version: 1.0
 */
public enum YesOrNoEnum implements BaseEnum {
    NO(0, "否"),
    YES(1, "是");
    

    private Integer code;

    private String message;


    YesOrNoEnum(int code, String message) {
        this.code = code;
        this.message = message;
    }


    public void setCode(int code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public Integer getCode() {
        return this.code;
    }

    @Override
    public String getMessage() {
        return this.message;
    }

    @Override
    public boolean isLoadDictionary() {
        return true;
    }

    @Override
    public String dictionaryName() {
        return BaseEnum.clearEnumClassTail(this.getClass());
    }


    @Override
    public boolean isDefaultAssembly() {
        return true;
    }

    public static boolean isYes(int code) {
        return Objects.equals(YES.getCode(), code);
    }

    public static boolean isNo(int code) {
        return Objects.equals(NO.getCode(), code);
    }

}

EnumDictionaryManager - 枚举字典管理器

import com.ceair.shoppingservice.base.exception.BaseBusinessException;
import com.ceair.shoppingservice.base.response.ResultCode;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AssignableTypeFilter;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 枚举字典管理器
 *
 * @author: Neo
 * @date: 2020/12/31 17:16
 * @version: 1.0
 */
@Slf4j
public class EnumDictionaryManager {

    public static final Map<String, List<EnumDictionary>> ENUMS = new ConcurrentHashMap<>(16);

    /**
     * 多个 , 号隔开
     */
    @Value("${enum.dictionary.manager.scanner.package:}")
    private String scannerPackage;

    @PostConstruct
    public void postConstruct() {
        initDictionary();
    }


    /**
     * 初始化字典
     *
     * @author: Neo
     * @date 2021/1/19 14:43
     * @version: 1.0
     */
    private void initDictionary() {
        log.info("枚举字典管理器【开始】");
        Stopwatch stopwatch = Stopwatch.createStarted();
        // 初始化枚举字典,默认仅扫描当前包路径下的类,可通过配置实现自定义
        if (StringUtils.isBlank(scannerPackage)) {
            scannerPackage = this.getClass().getPackage().getName();
        }

        List<String> scannerPackages = Splitter.on(";").omitEmptyStrings().trimResults().splitToList(scannerPackage);
        scannerPackages.forEach(this::initDictionary);

        log.info("枚举字典管理器【结束】,初始化耗时:{}/ms", stopwatch.elapsed(TimeUnit.MILLISECONDS));
    }

    /**
     * 初始化字典
     *
     * @author: Neo
     * @date 2021/1/19 14:43
     * @version: 1.0
     */
    private void initDictionary(String packageName) {
        log.info("开始加载 [{}] 包下的枚举", packageName);
        ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
        provider.addIncludeFilter(new AssignableTypeFilter(BaseEnum.class));
        Set<BeanDefinition> beans = provider.findCandidateComponents(packageName);

        for (BeanDefinition bean : beans) {
            try {
                Class<? extends BaseEnum> clazz = (Class<? extends BaseEnum>) Class.forName(bean.getBeanClassName());
                loadDictionary(clazz);
            } catch (ClassNotFoundException e) {
                log.error("ClassNotFoundException : [{}]", bean.getBeanClassName());
            }
        }
    }

    private <T extends BaseEnum> void loadDictionary(Class<? extends BaseEnum> e) {
        BaseEnum[] constants = e.getEnumConstants();

        Optional<BaseEnum> optional = Arrays.stream(constants).findFirst();

        if (!optional.isPresent()) {
            return;
        }

        BaseEnum baseEnum = optional.get();

        // 字典是否需要被加载
        if (!baseEnum.isLoadDictionary()) {
            return;
        }

        BaseBusinessException.ifThrow(ENUMS.containsKey(baseEnum.dictionaryName()), ResultCode.ENUM_DICTIONARY_NAME_EXIST);
        String dictionaryName = baseEnum.dictionaryName();
        // 字典获取策略
        ENUMS.put(dictionaryName, baseEnum.isDefaultAssembly() ? defaultAssembly(constants) : baseEnum.dictionaries());
        log.info("已加载字典[{}] ---> [{}]", baseEnum.getClass(), dictionaryName);
    }


    public Map<String, List<EnumDictionary>> ENUMS() {
        return ENUMS;
    }

    /**
     * 默认组装字典策略
     *
     * @param enumItems
     * @return
     */
    public static List<EnumDictionary> defaultAssembly(BaseEnum[] enumItems) {
        return BaseEnum.toDictionaries(enumItems);
    }

    /**
     * 获取字典通过字典名称
     *
     * @param dictionaryName
     * @return
     */
    public static List<EnumDictionary> getDictionariesByName(String dictionaryName) {
        return getDictionariesByName(dictionaryName, null);
    }

    /**
     * 获取字典通过字典名称
     *
     * @param dictionaryName
     * @param defaultValue
     * @return
     */
    public static List<EnumDictionary> getDictionariesByName(String dictionaryName, List<EnumDictionary> defaultValue) {
        List<EnumDictionary> result = ENUMS.get(dictionaryName);
        return Objects.nonNull(result) ? result : defaultValue;
    }


    /**
     * 获取字典通过字典名称
     *
     * @param clazz
     * @return
     */
    public static List<EnumDictionary> getDictionariesByClass(Class<? extends BaseEnum> clazz) {
        return getDictionariesByClass(clazz, null);
    }

    /**
     * 获取字典通过字典名称
     *
     * @param clazz
     * @param defaultValue
     * @return
     */
    public static List<EnumDictionary> getDictionariesByClass(Class<? extends BaseEnum> clazz, List<EnumDictionary> defaultValue) {
        if (Objects.isNull(clazz)) {
            return defaultValue;
        }
        return getDictionariesByName(clazz.getSimpleName(), defaultValue);
    }


    /**
     * 获取字典通过字典编码
     *
     * @param dictionaryName
     * @param code
     * @return
     */
    public static EnumDictionary getDictionaryByCode(String dictionaryName, Integer code) {
        List<EnumDictionary> dictionaries = getDictionariesByName(dictionaryName);
        if (CollectionUtils.isEmpty(dictionaries)) {
            return null;
        }
        Optional<EnumDictionary> optional = dictionaries.stream().filter(e -> Objects.equals(code, e.getCode())).findFirst();
        return optional.orElse(null);
    }

    /**
     * 获取字典通过字典编码
     *
     * @param clazz
     * @param code
     * @return
     */
    public static EnumDictionary getDictionaryByCode(Class<? extends BaseEnum> clazz, Integer code) {
        if (Objects.isNull(clazz)) {
            return null;
        }
        return getDictionaryByCode(clazz.getSimpleName(), code);
    }


    /**
     * 判断编码是否存在
     *
     * @param dictionaryName
     * @param code
     * @return
     */
    public static boolean containsCode(String dictionaryName, Integer code) {
        EnumDictionary dictionary = getDictionaryByCode(dictionaryName, code);
        return Objects.nonNull(dictionary);
    }

    /**
     * 判断编码是否存在
     *
     * @param clazz
     * @param code
     * @return
     */
    public static boolean containsCode(Class<? extends BaseEnum> clazz, Integer code) {
        if (Objects.isNull(clazz)) {
            return false;
        }
        return containsCode(clazz.getSimpleName(), code);
    }

    /**
     * 判断是否包含字典
     *
     * @param dictionaryName
     * @return
     */
    public static boolean containsDictionaries(String dictionaryName) {
        return ENUMS.containsKey(dictionaryName);
    }


    /**
     * 判断是否包含字典
     *
     * @param clazz
     * @return
     */
    public static boolean containsDictionaries(Class<? extends BaseEnum> clazz) {
        if (Objects.isNull(clazz)) {
            return false;
        }
        return containsDictionaries(clazz.getSimpleName());
    }
}

使用示例:EnumDictionaryManagerConfig

import com.ceair.shoppingservice.base.eunms.EnumDictionaryManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 枚举字典管理器配置
 *
 * @author: Neo
 * @date: 2021/1/19 11:20
 * @version: 1.0
 */
@Configuration
public class EnumDictionaryManagerConfig {

    @Bean
    public EnumDictionaryManager enumDictionaryManager() {
        return new EnumDictionaryManager();
    }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值