Java 通过反射获取注解属性信息以及状态中字典(方式一)
一、创建存储对象
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 属性对象存储类*/ public class MetadataField { /** * key 对应对象中间的属性 */ private String key; /** * 字段标签 */ private String label; /** * 列表形式的字典 */ private List<Map<String, String>> dictionaries; public MetadataField(String key, String label) { this.key = key; this.label = label; this.dictionaries = new ArrayList<>(); } public String getKey() { return key; } public String getLabel() { return label; } public void setKey(String key) { this.key = key; } public void setLabel(String label) { this.label = label; } public List<Map<String, String>> getDictionaries() { return dictionaries; } public void setDictionaries(List<Map<String, String>> dictionaries) { this.dictionaries = dictionaries; } // 添加一个方法,用于往 dictionaries 中添加字典项 public void addDictionaryItem(String key, String value) { Map<String, String> dictionaryItem = new HashMap<>(); dictionaryItem.put("key", key); dictionaryItem.put("value", value); this.dictionaries.add(dictionaryItem); } }
二、工具类(通过ApiModelProperty注解获取字段属性信息)
/** * 对象属性封装类*/ public class ReflectionUtils { /** * 获取指定类的属性元数据列表,包括字段名称、中文标签和字典信息。 * * @param clazz 要获取元数据的类 * @param <T> 类型参数 * @return 包含属性元数据的列表 */ public static <T> List<MetadataField> getField(Class<T> clazz) { List<MetadataField> propertyMetadataList = new ArrayList<>(); Field[] fields = clazz.getDeclaredFields(); // 处理字段 for (Field field : fields) { ApiModelProperty annotation = field.getAnnotation(ApiModelProperty.class); if (annotation != null) { String propertyName = field.getName(); String chineseName = annotation.value(); // 将驼峰命名转换为下划线命名 String underscoredName = camelToUnderscore(propertyName); propertyMetadataList.add(new MetadataField(underscoredName, chineseName)); } } // 获取所有的 getter 方法 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (isGetter(method)) { try { // 调用 getter 方法获取属性值 Object value = method.invoke(clazz.getDeclaredConstructor().newInstance()); // 处理返回字典的方法 if (value instanceof Map) { Map<?, ?> dictionary = (Map<?, ?>) value; // 查找对应的 MetadataField MetadataField metadataField = findMetadataFieldByPropertyName(propertyMetadataList, getPropertyNameFromGetter(method)); if (metadataField != null) { for (Map.Entry<?, ?> entry : dictionary.entrySet()) { metadataField.addDictionaryItem(entry.getKey().toString(), entry.getValue().toString()); } } } } catch (Exception e) { handleReflectionException(e); } } } return propertyMetadataList; } /** * 将驼峰命名转换为下划线命名。 * * @param propertyName 驼峰命名的字符串 * @return 下划线命名的字符串 */ private static String camelToUnderscore(String propertyName) { StringBuilder result = new StringBuilder(); for (char ch : propertyName.toCharArray()) { if (Character.isUpperCase(ch)) { result.append("_").append(Character.toLowerCase(ch)); } else { result.append(ch); } } return result.toString(); } /** * 判断方法是否为 getter 方法。 * * @param method 要检查的方法 * @return 如果是 getter 方法则返回 true,否则返回 false */ private static boolean isGetter(Method method) { return method.getName().startsWith("get") && method.getParameterCount() == 0; } /** * 从 getter 方法中获取属性名称。 * * @param method getter 方法 * @return 属性名称 */ private static String getPropertyNameFromGetter(Method method) { String methodName = method.getName(); return methodName.substring(3, 4).toLowerCase() + methodName.substring(4); } /** * 根据属性名称查找对应的 MetadataField。 * * @param fields 属性元数据列表 * @param propertyName 要查找的属性名称 * @return 匹配的 MetadataField,如果找不到则返回 null */ private static MetadataField findMetadataFieldByPropertyName(List<MetadataField> fields, String propertyName) {
// 将驼峰命名转换为下划线命名
String underscoredName = camelToUnderscore(propertyName); for (MetadataField field : fields) { if (propertyName.equals(field.getKey())) { return field; } } return null; } /** * 处理反射异常。 * * @param e 反射异常 */ private static void handleReflectionException(Exception e) { // 处理反射异常 e.printStackTrace(); } }
三、构建 ApiModelProperty注解对象
import com.fasterxml.jackson.annotation.JsonFormat; import com.yf.mybatis.entity.BaseEntity; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDateTime; import java.util.Date; import java.util.HashMap; import java.util.Map; @Data @NoArgsConstructor @AllArgsConstructor public class DeductionDTO{ @ApiModelProperty("总负责人") private String head; /** * 状态(0推进中 1已停滞 2已完成) */ @ApiModelProperty("状态") private Map<String, Integer> status; // 获取 status 字段的 getter 方法 public Map<String, Integer> getStatus() { Map<String, Integer> statusMapping = new HashMap<>(); statusMapping.put("推进中", 0); statusMapping.put("已停滞", 1); statusMapping.put("已完成", 2); return statusMapping; } /** * 分类(0退税 1抵扣 2退税到账) */ @ApiModelProperty("分类") private String type; public Map<String, Integer> getType() { Map<String, Integer> statusMapping = new HashMap<>(); statusMapping.put("退税", 0); statusMapping.put("抵扣", 1); statusMapping.put("退税到账", 2); return statusMapping; } @ApiModelProperty("创建时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; }
四、前端控制器调用
@PostMapping("/testField") public R<List<MetadataField>> testField(){ // 获取属性名和中文描述的映射 List<MetadataField> field = ReflectionUtils.getField(DeductionDTO.class); return R.data(field); }
返回结果如下:
{ "code": 0, "msg": "操作成功", "data": [ { "key": "head", "label": "总负责人", "dictionaries": [] }, { "key": "type", "label": "分类", "dictionaries": [ { "value": "1", "key": "抵扣" }, { "value": "2", "key": "退税到账" }, { "value": "0", "key": "退税" } ] }, { "key": "status", "label": "状态", "dictionaries": [ { "value": "2", "key": "已完成" }, { "value": "0", "key": "推进中" }, { "value": "1", "key": "已停滞" } ] }, { "key": "create_time", "label": "创建时间", "dictionaries": [] } ] }