`
xmong
  • 浏览: 263483 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Memo class备注类信息

阅读更多
Memo Class
1. 什么是Memo Class
Memo class其实就是备注类信息,很多人会问为什么要备注类信息,其实这个功能词汇并不常见,但是我就是在开发过程中遇到了这个功能实现。场景是这样的,我要实现一个通知模块,负责根据流程配置来处理消息,然后将消息发送出去。其中有一个步骤就是根据消息模板渲染消息,在这个渲染过程中,如果模板是页面可管理的,那么页面在配置模板的时候,要知道消息数据中的键值对应该模板中热数据的键值是什么,显然模板是页面可管理的,那么就是要模板的键值依赖于调用者传入的接口模型数据,在这种条件下要管理模板就需要知道调用者的数据模型键值说明,这个时候如果能把这个数据模型备注出来让模板管理者查看,那么模板管理者就能很好的管理自己的模板,根据需要调整要显示的数据。

上面的场景可能过于拗口,简单点说就是在一些大的项目中,我们需要将我们模型数据展示到页面上方便管理和让其他使用的人查看。

2. Memo Class的案例
如下需要将下面简单的数据模型 MsgObject的属性信息构建展示出去,让使用者在页面可以查看属性信息,我们可以通过构建类的注解来备注该数据模型,提取其中的注解信息展示出去,类构建如下:

package com.annotation.memo;

/**
 * @author xmong
 */
public class MsgObject {

    @MsgType(memo="消息名称")
    String name;
    
    @MsgType(memo="测试消息")
    MsgTest msgTest;
}

class MsgTest{
    
    @MsgType(memo="名称")
    String name; 
    
}


自定义注解类,有用注解备注类属性和class的信息,相当于给模型数据配置了一个xml信息文档说明。

package com.annotation.memo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 注解类,备注类信息
 * @author xmong
 */
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgType {

    /**
     * key值注解,默认值为空字符串
     * @return
     */
    public String key() default AnnotationConfig.DEFAULT_KEY;
    
    /**
     * 备注注解,默认值为空字符串
     * @return
     */
    public String memo() default AnnotationConfig.DEFAULT_MEMO;
    
}


package com.annotation.memo;
/**
 * @author xmong
 */
public interface AnnotationConfig {

    //key 默认值
    public String DEFAULT_KEY = "";
    
    //备注默认值
    public String DEFAULT_MEMO = "";
}


存储注解信息的对象模型类


package com.annotation.memo;

/**
 * 备注信息封装类
 * @author xmong
 */
public class MsgMemo {

    /**
     * key值,对于类属性名或者是备注key
     */
    private String key;
    
    /**
     * 备注信息
     */
    private String memo;
    
    /**
     * 值类型
     */
    private String type;

    /**
     * 默认属性分隔符
     */
    public static String DEFAULT_SPLIT_SIGN = ".";
    
    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public String getMemo() {
        return memo;
    }
    public void setMemo(String memo) {
        this.memo = memo;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    } 
    public void appendKey(String key){
        this.key = null == this.key ? key : this.key+DEFAULT_SPLIT_SIGN+key;
    }
    
    public void appendMemo(String memo){
        this.memo = null == this.memo ? memo : this.memo+DEFAULT_SPLIT_SIGN+memo;
    }
    @Override
    public String toString() {
        return "{key:"+getKey()
                +", memo:"+getMemo()
                +", type:"+getType()+"}";
    }
    
}


注解处理备注类实现如下,通过类结构反射遍历数据模型属性,逐层递归处理我们想要展示的结果,实现如下:


package com.annotation.memo;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 备注构建类
 * @author xmong
 */
public class AnnotationMsgHandler {

    /**
     * map对象名为key,value为对象属性注解信息类列表
     */
    public static Map<String, List<MsgMemo>> memoMap = new HashMap<String, List<MsgMemo>>();
    
    /**
     * 对象属性注解信息列表类
     */
    public static List<MsgMemo> memoList = new ArrayList<MsgMemo>();
    
    /**
     * 静态代码执行
     */
    static{
        doBuilderMsgList(new MsgObject());
        doBuilderMsgMap(new MsgObject());
    }
    
    
    public static void doBuilderMsgMap(Object obj){
        builderMsgMap(obj.getClass(), memoMap);
    }
    
    public static void doBuilderMsgList(Object obj){
        builderMsgList(obj.getClass(), memoList, null, null);
    }
   
    public static void builderMsgMap(Class<?> c, Map<String, List<MsgMemo>> map){
        //获取类的属性
        Field[] fields = c.getDeclaredFields();
        List<MsgMemo> list = new ArrayList<MsgMemo>();
        //根据类名保存属性列表
        map.put(c.getSimpleName(), list);
        //遍历属性
        for (Field field : fields) {
            //判断属性是否被注解,没有被注解则进入下一次循环
            if(!field.isAnnotationPresent(MsgType.class)) continue;
            //获取注解
            MsgType msgType = field.getAnnotation(MsgType.class);
            //获取注解key值,如果key存在,则属性为key值,如果属性为默认值则属性为类属性名
            String keyMsg = AnnotationConfig.DEFAULT_KEY.equals(msgType.key())
                    ? field.getName() : msgType.key();
            //构建属性信息
            MsgMemo msgMemo = new MsgMemo();
            msgMemo.appendKey(keyMsg);
            msgMemo.appendMemo(msgType.memo());
            msgMemo.setType(field.getGenericType().toString());
            list.add(msgMemo); //属性注解加入列表
            /**
             * 判断是否为java常用类,如果不为java基本变量和java常用类,
             * 则继续递归处理该属性类循环,反之既然
             */
            if(field.getType().toString().toLowerCase().startsWith("class")
                    &&!field.getType().getName().startsWith("java.lang")
                    &&!field.getType().getName().startsWith("java.util")){
                //递归调用
                builderMsgMap(field.getType(), map);
            }
        }
       
    }
    
    
    public static void builderMsgList(Class<?> c, List<MsgMemo> list, String key, String memo){
        //获取类属性
        Field[] fields = c.getDeclaredFields();
        //遍历类属性
        for (Field field : fields) {
            if(!field.isAnnotationPresent(MsgType.class)) continue;
            MsgType msgType = field.getAnnotation(MsgType.class);
            String keyMsg = AnnotationConfig.DEFAULT_KEY.equals(msgType.key())
                    ? field.getName() : msgType.key();
            MsgMemo msgMemo = new MsgMemo();
            msgMemo.setKey(key);
            msgMemo.setMemo(memo);
            msgMemo.appendKey(keyMsg);
            msgMemo.appendMemo(msgType.memo());
            /**
             * 如果属性为基本变量和常用类,则保存到列表中
             * 反之则递归处理该属性类
             */
            if(!field.getType().toString().toLowerCase().startsWith("class")
                    ||field.getType().getName().startsWith("java.lang")
                    ||field.getType().getName().startsWith("java.util")){
                msgMemo.setType(field.getGenericType().toString());
                list.add(msgMemo);
            }else{
                //递归调用
                builderMsgList(field.getType(), list, msgMemo.getKey(), msgMemo.getMemo());
            }
        }
       
    }
    
    public static Map<String, List<MsgMemo>> getMemoMap() {
        return memoMap;
    }

    public static void setMemoMap(Map<String, List<MsgMemo>> memoMap) {
        AnnotationMsgHandler.memoMap = memoMap;
    }

 
    public static List<MsgMemo> getMemoList() {
        return memoList;
    }

    public static void setMemoList(List<MsgMemo> memoList) {
        AnnotationMsgHandler.memoList = memoList;
    }
    
    
    
    
}



测试类实现

package com.annotation.memo;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author xmong
 */
public class Test {

    
    
    public static void main(String[] args) {
        /**
         * 遍历列表输出注解信息
         */
        List<MsgMemo> list = AnnotationMsgHandler.getMemoList();
        for (MsgMemo msgMemo : list) {
            System.out.println(msgMemo);
        }
        /**
         * 遍历map输出类注解信息
         */
        Map<String, List<MsgMemo>>  map = AnnotationMsgHandler.getMemoMap();
        for (Entry<String, List<MsgMemo>> entry : map.entrySet()) {
            System.out.println(entry);
        }
        
        
    }
}


运行结果:
{key:name, memo:消息名称, type:class java.lang.String}
{key:msgTest.name, memo:测试消息.名称, type:class java.lang.String}
MsgObject=[{key:name, memo:消息名称, type:class java.lang.String}, {key:msgTest, memo:测试消息, type:class com.annotation.memo.MsgTest}]
MsgTest=[{key:name, memo:名称, type:class java.lang.String}]


从结果可以看出,已将备注类的信息输出




分享到:
评论

相关推荐

    memo-decorator:将备注应用于类方法的装饰器

    此装饰器将备注应用于类的方法。 用法 将装饰器应用于类的方法。 缓存是该方法的本地缓存,但在该类的所有实例之间共享。 强烈建议您仅在纯方法上使用此装饰器。 安装: npm i memo-decorator --save 配置 export ...

    书店管理系统的SQL

    11. MEMO(备注):用于记录关于书籍的其他信息,如简介、评论等,VARCHAR2(100)可变长度字符串。 出售信息表记录了每笔销售交易的细节: 1. SELLTIME(销售时间):交易发生的时间,NOT NULL的DATE类型。 2. ISBN...

    2021-2022计算机二级等级考试试题及答案No.11088.docx

    在数据库操作中,某些字段类型如备注型(Memo)不支持排序,而文本型、数字型和自动编号型则可以;在.NET框架中,验证控件如`CompareValidator`和`RequiredFieldValidator`组合使用可以验证TextBox控件输入的年龄...

    SAP会计科目自动分配配置大全.docx

    和科目备注 Memo。 五、实践示例 例如,在 AG1、AG2 和 AG3 中,用户可以配置不同的科目分配规则,例如根据不同的 valuation class 配置不同的价差科目。在跨公司库存转移时可能会加上运输费等,用户可以给某类 ...

    JSP中使用数据库 汇总.txt

    1. **数据库建表**:首先,需要在SQL Server中创建一个名为`student`的表,并定义相应的字段,如`学号(sno)`、`姓名(sname)`、`密码(password)`和`备注(memo)`。 - **SQL语句示例**: ```sql CREATE TABLE ...

    JSP中使用数据库1 前期准备

    - **备注** (`memo`):用于存储关于学生的额外信息。 可以通过以下SQL命令创建这个表: ```sql CREATE TABLE student ( sno INT PRIMARY KEY, sname VARCHAR(50), password VARCHAR(50), memo VARCHAR(255) );...

    ECSide入门

    &lt;ecs:column property="memo" title="备注"/&gt; ``` #### 五、总结 通过上述步骤,我们可以看到ECSide极大地简化了Web应用中列表数据的展示过程。它不仅提高了开发效率,还使得页面的布局更加灵活。对于初学者来...

    支付宝到账DEMO.exe

    appId=09999988&actionType=toAccount&goBack=NO&amount=1.00&userId=2088501156491651&memo=备注2088501156491651 具体的链接:alipays://platformapi/startapp?appId=09999988&actionType=toAccount&goBack=NO&...

    第四次上机练习题目1

    G_SpecialityInfo 表格用于记录专业信息,包含专业代码(SpecialityID)、专业名称(SpecialityName)、学年(StudyYear)和备注(Memo)。专业代码是主键。 G_CourseInfo 表格存储课程信息,包括课程代码...

    JSP中使用数据库3 添加数据.txt

    备注:&lt;input type="text" name="memo"&gt; 新增"/&gt; ``` ##### 2. 数据库连接与操作 在`insdataok.jsp`页面中,我们首先建立与数据库的连接,然后根据用户提交的数据执行SQL插入语句。 **数据库连接代码示例...

    2021-2022计算机二级等级考试试题及答案No.17340.docx

    13. 备注字段(Memo Field)通常不能用于建立索引,因为它们通常包含长文本,不适合快速查找。 14. 表格式窗体可以同时显示多条记录,适合于浏览和编辑大量数据。 15. 在UDP通信中,使用DatagramPacket的...

    基于C/S 模式的客户端软件系统

    - `memo`: 备注信息。 - **文件类别数据库(type_file)**:用于定义文件的类别。 - 字段: - `Number`: 文件编号。 - `File_name`: 文件名称。 - `File_blob`: 文件内容。 - `File_class`: 文件所属类别。...

    医嘱数据接口专项方案中间表.doc

    12. DOCTOR_MEMO: 医生说明,用于记录医生对医嘱的额外指示或备注。 13. RELATION_KEY: 医嘱关联的唯一号,可能关联到其他统计信息。 14. PRICE: 医嘱的价格,以货币形式表示。 15. CTRL_INFO: 医嘱控制信息,...

    2021-2022计算机二级等级考试试题及答案No.18136.docx

    27. **排序字段数据类型**:备注型字段(Memo Field)通常不支持直接的排序操作,因为它们通常包含较长的文本或富文本内容。 28. **数据库记录指针**:在数据库操作中,可以通过SQL命令或特定API相对移动或绝对移动...

    2021-2022计算机二级等级考试试题及答案No.16529.docx

    - 表中的字段类型包括文本(Text)、日期(Date)和备注(Memo),但不包括索引(Index),索引是用于加速查询的数据结构。 2. 操作系统概念: - 计算机操作系统的主要功能是管理计算机系统的软硬件资源,提高...

    JSP中使用数据库2 主页面.txt

    备注:("memo")%&gt; } } else { System.out.println("连接数据库失败!"); } %&gt; 更新数据&lt;/a&gt;&lt;br/&gt; 增加数据&lt;/a&gt;&lt;br/&gt; 删除数据&lt;/a&gt;&lt;br/&gt; ``` #### 四、总结 本篇示例代码展示了如何在JSP页面中...

    spring security配置实例

    - `memo`: 描述备注。 - `url`: 对应URL路径。 - `priority`: 权限优先级。 - `type`: 权限类型。 - `name`: 权限编码。 - `id`: 自增长主键。 5. **角色_资源表 (`roles_resources`)**: - `rsid`: 资源表...

    2021-2022计算机二级等级考试试题及答案No.16384.docx

    17. Access索引:备注型字段(Memo Field)在Access中无法建立索引,不利于快速查找。 18. Web浏览:要访问某个公司的主页,需要知道该公司的WWW地址,即网址。 19. ASP.NET验证控件:ASP.NET提供了多种验证控件,...

    2021-2022计算机二级等级考试试题及答案No.5415.docx

    14. 表字段类型:表字段通常包括文本(Text)、日期(Date)、备注(Memo)等,索引(Index)不是字段类型,而是用于提高查询效率的结构。 15. 关系数据库记录顺序:关系数据库中的记录没有固定的前后顺序,可以...

Global site tag (gtag.js) - Google Analytics