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,不过因为有些实体类的属性在表里面是没有的,所以才有这个根据实体类来解析的实现。

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

相关推荐
ᝰꫝꪉꪯꫀ361几秒前
JavaWeb——Mybatis
java·开发语言·后端·mybatis
没有黑科技13 分钟前
网上蛋糕售卖店管理系(Java+SpringBoot+MySQL)
java·spring boot·mysql
是老余14 分钟前
算法之区间和题目讲解
java·算法
✿゚卡笨卡20 分钟前
java大视频分片上传
java·大文件上传
THRUSTER1111144 分钟前
Java学习笔记--继承的介绍,基本使用,成员变量和成员方法访问特点
java·开发语言·笔记·学习·学习方法·继承·intellij idea
沉河不浮44 分钟前
Java基础——(一)Java概述
java·开发语言
paterWang1 小时前
小程序-基于java+SpringBoot+Vue的网上花店微信小程序设计与实现
java·spring boot·小程序
paterWang1 小时前
小程序-基于java+SpringBoot+Vue的美食推荐系统设计与实现
java·spring boot·小程序
《源码好优多》1 小时前
基于Java Springboot餐饮美食分享平台
java·spring boot·美食
说书客啊1 小时前
计算机毕业设计 | SpringBoot+vue美食推荐商城 食品零食购物平台(附源码+论文)
java·spring boot·node.js·vue·毕业设计·课程设计·美食