前言
获取某个类的属性(字段)是我们经常都会碰到的,通常我们是通过反射来获取的。
但是有些特殊情况下,我们不仅要获取类的属性,还需要获取属性注释。这种情况下,我们只能通过注解去获取注释。可以自己定义一个专门用于设置注释的注解;如果项目中用了swagger的话,那就可以直接用swagger的@ApiModelProperty注解,这样就不用再单独自定义一个注解了。
假如不想通过反射和注解来获取也可以,那就可以通过以读取文件的形式读取这个java文件,解析注释和属性名。
实现
通过反射和注解获取
首先自定义一个注解(有用swagger就不用再定义了,直接用@ApiModelProperty就行)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 注释注解*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment {String value() default "";
}
使用:
@Data
public class SysUser {// 这两个注解任意选一个就行@Comment("名称")@ApiModelProperty(value = "名称")private String name;
}
反射获取:
public static void main(String[] args) {Map<String,String> map = new LinkedHashMap<>();StringBuilder sb = new StringBuilder(); // 转json格式sb.append("{\n");// 设置公共属性sb.append("\t\"").append("id").append("\"").append(":").append("\"").append("id").append("\"").append(",\n");sb.append("\t\"").append("creatorId").append("\"").append(":").append("\"").append("创建者").append("\"").append(",\n");sb.append("\t\"").append("createTime").append("\"").append(":").append("\"").append("创建时间").append("\"").append(",\n");sb.append("\t\"").append("updateId").append("\"").append(":").append("\"").append("更新者").append("\"").append(",\n");sb.append("\t\"").append("updateTime").append("\"").append(":").append("\"").append("更新时间").append("\"").append(",\n");Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();//String fieldComment = field.getAnnotation(ApiModelProperty.class).value();String fieldComment = field.getAnnotation(Comment.class).value();sb.append("\t\"").append(fieldName).append("\"").append(":").append("\"").append(fieldComment).append("\"").append(",\n");map.put(fieldName, fieldComment);}sb.append("}");System.out.println(map);System.out.println(sb.toString());
}
输出结果:
读取文件的形式解析
要解析的类:
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.common.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;import java.util.List;
import java.util.Map;/*** 用户信息*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("sys_user")
public class SysUser extends BaseEntity {/*** 用户名称*/@TableField("user_name")private String userName;/*** 用户姓名*/@TableField("real_name")private String realName;/*** 所属部门*/@TableField("dept_id")private String deptId;/*** 所属角色*/@TableField("role_id")private String roleId;/*** 状态(1 启用 2 停用)*/@TableField("state")private Integer state;/** token值 */@TableField(exist = false)private String token;// 部门名称@TableField(exist = false)private String deptName;/** 上级部门id*/@TableField(exist = false)private String parentId;/* 上级部门名称 */@TableField(exist = false)private String parentName;/***角色代码*/@TableField(exist = false)private String roleKey;/***角色名称*/@TableField(exist = false)private String roleName;/**角色信息*/@TableField(exist = false)private SysRole role;// 部门列表@TableField(exist = false)private List<SysDept> deptList;//部门列表@TableField(exist = false)private Map<String,Object> params;
}
上面的注释有单行注释、多行注释
开始解析:
/*** @param flag 是否需要拼接公共属性 true 需要 false 不用*/
private static void entityToJSON(boolean flag){System.out.println("请输入实体类文件路径:");Scanner sc = new Scanner(System.in);String filePath = sc.next();File file = new File(filePath);if (!file.exists()){System.out.println("文件不存在!");return;}BufferedReader br = null;StringBuilder sb = new StringBuilder();sb.append("{\n");if (flag){// 设置公共属性sb.append("\t\"").append("id").append("\"").append(":").append("\"").append("id").append("\"").append(",\n");sb.append("\t\"").append("creatorId").append("\"").append(":").append("\"").append("创建者").append("\"").append(",\n");sb.append("\t\"").append("createTime").append("\"").append(":").append("\"").append("创建时间").append("\"").append(",\n");sb.append("\t\"").append("updateId").append("\"").append(":").append("\"").append("更新者").append("\"").append(",\n");sb.append("\t\"").append("updateTime").append("\"").append(":").append("\"").append("更新时间").append("\"").append(",\n");}try{br = new BufferedReader(new FileReader(file));String line = "";// 属性名、注释、上一个属性名String key = "",value = "",preKey = "",preValue = "";while ((line = br.readLine()) != null){String 内容 = line.trim(); // 每一行的内容,去掉空格//System.out.println(内容);if (内容.length() > 0){if ((内容.startsWith("*") && !内容.endsWith("*/")) || 内容.startsWith("//") || (内容.startsWith("/*") && 内容.endsWith("*/"))){// 这里是解析属性注释value = 内容.replace("/*","").replace("*/","").replace("*","").replace("//","").trim();}else if (内容.startsWith("private")){// 这里是解析以 private 开头的属性名称//key = 内容.replaceAll("private String |private Integer |private Long |private Double |;|private List<.*> ", "");key = 内容.replaceAll("private .* |;", "").trim();}// 这里按照一行一行解析文件的话,注释是比属性先解析出来的,所以不能直接put// key不为空,并且不等于上一个属性名时才putif (StrUtil.isNotBlank(key) && !key.equals(preKey)){// 当前属性和前一个注释才是相对应的sb.append("\t\"").append(key).append("\"").append(":").append("\"").append(value).append("\"").append(",\n");}preKey = key;}}}catch (Exception e){e.printStackTrace();}finally {try {br.close();} catch (IOException e) {e.printStackTrace();}}sb.append("}");System.out.println(sb.toString());
}
输出结果:
这样我们就可以将实体类转成JSON格式了。
最后
其实我是因为写接口文档需要用到json格式的数据,所以才想要获取属性注释。
一开始我是用实体类对应的数据库表来解析的,也就是解析一段建表SQL,不过因为有些实体类的属性在表里面是没有的,所以才有这个根据实体类来解析的实现。
如果有跟我一样需要用到 获取属性注释
的,可以参考下。