Java解析实体类的属性和属性注释

前言

获取某个类的属性(字段)是我们经常都会碰到的,通常我们是通过反射来获取的。

但是有些特殊情况下,我们不仅要获取类的属性,还需要获取属性注释。这种情况下,我们只能通过注解去获取注释。可以自己定义一个专门用于设置注释的注解;如果项目中用了swagger的话,那就可以直接用swagger的@ApiModelProperty注解,这样就不用再单独自定义一个注解了。

假如不想通过反射和注解来获取也可以,那就可以通过以读取文件的形式读取这个java文件,解析注释和属性名。

实现

通过反射和注解获取

首先自定义一个注解(有用swagger就不用再定义了,直接用@ApiModelProperty就行)

java 复制代码
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 "";
}

使用:

java 复制代码
@Data
public class SysUser {
	// 这两个注解任意选一个就行
    @Comment("名称")
    @ApiModelProperty(value = "名称")
    private String name;
}

反射获取:

java 复制代码
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());
}

输出结果:

读取文件的形式解析

要解析的类:

java 复制代码
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;
}

上面的注释有单行注释、多行注释

开始解析:

java 复制代码
/**
 * @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不为空,并且不等于上一个属性名时才put
                if (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,不过因为有些实体类的属性在表里面是没有的,所以才有这个根据实体类来解析的实现。

如果有跟我一样需要用到 获取属性注释 的,可以参考下。

相关推荐
九圣残炎14 分钟前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge16 分钟前
Netty篇(入门编程)
java·linux·服务器
Re.不晚43 分钟前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐1 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
顾北川_野1 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
confiself1 小时前
大模型系列——LLAMA-O1 复刻代码解读
java·开发语言
Wlq04151 小时前
J2EE平台
java·java-ee
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】Thread类的方法&线程生命周期
java·开发语言·java-ee