Java 扫描枚举类并获取属性

Java 扫描枚举类并获取属性

第一步:在 pom.xml 下导入 hutool 和 commons-lang3

<!--hutool-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.0.M2</version>
</dependency>

<!--commons-lang3-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

第二步:写一个接口以规范枚举的属性

package com.zibo.api.myinterfaces;

// 枚举实现该接口,用于约束枚举必须有 key 和 value 两个字段,及其 getter 方法,以符合反射获取和调用方法
public interface MyEnum {
    int getKey();
    String getValue();
}

第三步:写一个枚举属性包装类

package com.zibo.api.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

// 封装枚举数据
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EnumDto {
    private Integer key;
    private String value;
}

第四步:写两个实体测试类

Dog

package com.zibo.api.enums;

import com.zibo.api.myinterfaces.MyEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum Dog implements MyEnum {
    A(1, "刘备"),
    B(2, "关羽"),
    C(3, "张飞");
    private int key;
    private String value;
}

Cat

package com.zibo.api.enums;

import com.zibo.api.myinterfaces.MyEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum Cat implements MyEnum {
    A(1, "大哥"),
    B(2, "二哥"),
    C(3, "三哥");
    private int key;
    private String value;
}

第五步:写一个枚举扫描工具类

注意使用时需要根据实际需求进行调整!

package com.zibo.api.utils;

import cn.hutool.core.util.ClassUtil;
import com.zibo.api.entity.EnumDto;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

// 获取枚举类的所有属性
public class EnumUtils {

    // 扫描的包路径
    private static final String basePackage = "com.zibo.api";

    public static Map<String, List<EnumDto>> enums = null;

    static {
        try {
            enums = getEnums();
        } catch (InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private EnumUtils() {}

    private static Map<String, List<EnumDto>> getEnums() throws InvocationTargetException, IllegalAccessException {
        // map 的规则是覆盖,如果存在多个相同的 key 不会报错,因此写一个 set 以验证之
        Set<String> set = new HashSet<>();
        // 扫描该包路径下所有class文件
        Set<Class<?>> classes = ClassUtil.scanPackage(basePackage);
        // 用来存放扫描到的符合要求的【所有枚举】信息,要求参考“ClassUtil.getDeclaredMethod”
        Map<String, List<EnumDto>> enums = new HashMap<>();
        // 用来存放【当前枚举】的所有属性
        List<EnumDto> list;
        for (Class<?> aClass : classes) {
            // 判断类是否为枚举类型
            if (ClassUtil.isEnum(aClass)) {
                // 枚举必须有这两个字段,当然也可以根据需求定义更多,将 EnumDto 做相应调整即可!
                Method keyMethod = ClassUtil.getDeclaredMethod(aClass, "getKey");
                Method valueMethod = ClassUtil.getDeclaredMethod(aClass, "getValue");
                if (keyMethod == null || valueMethod == null) continue;
                // 得到 enum 的所有实例:一个数组,该数组包含组成此 Class 对象表示的枚举类的值,按它们声明的顺序
                Object[] objs = aClass.getEnumConstants();
                // 装载当前枚举所有值
                list = new ArrayList<>();
                for (Object obj : objs) list.add(new EnumDto((Integer) keyMethod.invoke(obj), (String) valueMethod.invoke(obj)));
                // 装载当前枚举 list 到所有枚举 map
                String enumName = aClass.getName().substring(aClass.getName().lastIndexOf(".") + 1);
                String prefix = "com.zibo";
                String moduleName = aClass.getName().substring(aClass.getName().indexOf(".", prefix.length()) + 1, aClass.getName().indexOf(".", prefix.length() + 1));
                String key = StringUtils.join(moduleName, ".", enumName);
                if (!set.add(key)) throw new RuntimeException("同一模块下存在重复枚举名!格式:模块名.枚举名,内容:" + key);
                enums.put(key, list);
            }
        }
        return enums;
    }
}

第六步:代码测试

package com.zibo.api;

import com.zibo.api.utils.EnumUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MyEnumTest {
    @Test
    public void test() {
        EnumUtils.enums.forEach((k, v) -> {
            System.out.println(k + ":");
            v.forEach(System.out::println);
        });
    }
}

第七步:运行结果

api.Dog:
EnumDto(code=1, text=刘备)
EnumDto(code=2, text=关羽)
EnumDto(code=3, text=张飞)
api.Cat:
EnumDto(code=1, text=大哥)
EnumDto(code=2, text=二哥)
EnumDto(code=3, text=三哥)

第八步:实际使用说明

1、(必须)要返回的枚举必须遵守 MyEnum 接口规范,不一定要实现该接口,但必须有 getKey 和 getValue 两个方法;

2、(建议)建议在登录完成后等场景调用一次该接口(写成的api接口),并缓存到客户端;

3、(提示)本接口全部相关类(用来测试的测试实体类除外):EnumDto、MyEnum、EnumUtils。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值