- 浏览: 264159 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (88)
- JAVA / base (26)
- JAVA / web (12)
- JAVA / Lib-tools (5)
- SERVER / tomcat (4)
- DB / mysql (4)
- DB / mongodb (2)
- DB / memcached (2)
- DB / redis (2)
- WEB / Front-end (3)
- WEB / security (4)
- WEB / css (2)
- WEB / js (4)
- OS / linux (3)
- IT / Architecture (4)
- IT / other (2)
- Android (9)
- Go (1)
- Other (1)
- OS / Mac (2)
最新评论
-
Zero2Max:
哈哈,马士兵老师也发现了。
java实现接口的bug -
xly1981:
能像CSRF攻击一样带个图就更棒了
XSS跨站攻击 -
xmong:
df274119386 写道在javascript中看到下面的 ...
CSRF攻击与防御策略 -
df274119386:
在javascript中看到下面的语句 e.value = t ...
CSRF攻击与防御策略 -
xmong:
yzxqml 写道xmong 写道yzxqml 写道tomca ...
Tomcat集群
Memo Class
1. 什么是Memo Class
Memo class其实就是备注类信息,很多人会问为什么要备注类信息,其实这个功能词汇并不常见,但是我就是在开发过程中遇到了这个功能实现。场景是这样的,我要实现一个通知模块,负责根据流程配置来处理消息,然后将消息发送出去。其中有一个步骤就是根据消息模板渲染消息,在这个渲染过程中,如果模板是页面可管理的,那么页面在配置模板的时候,要知道消息数据中的键值对应该模板中热数据的键值是什么,显然模板是页面可管理的,那么就是要模板的键值依赖于调用者传入的接口模型数据,在这种条件下要管理模板就需要知道调用者的数据模型键值说明,这个时候如果能把这个数据模型备注出来让模板管理者查看,那么模板管理者就能很好的管理自己的模板,根据需要调整要显示的数据。
上面的场景可能过于拗口,简单点说就是在一些大的项目中,我们需要将我们模型数据展示到页面上方便管理和让其他使用的人查看。
2. Memo Class的案例
如下需要将下面简单的数据模型 MsgObject的属性信息构建展示出去,让使用者在页面可以查看属性信息,我们可以通过构建类的注解来备注该数据模型,提取其中的注解信息展示出去,类构建如下:
自定义注解类,有用注解备注类属性和class的信息,相当于给模型数据配置了一个xml信息文档说明。
存储注解信息的对象模型类
注解处理备注类实现如下,通过类结构反射遍历数据模型属性,逐层递归处理我们想要展示的结果,实现如下:
测试类实现
运行结果:
从结果可以看出,已将备注类的信息输出
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}]
从结果可以看出,已将备注类的信息输出
发表评论
-
Java validation(java验证器实现)
2014-03-18 11:45 3732Java validation 1. java验证器 在 ... -
java annotation注解
2014-01-24 18:01 9571. Annotation的声明方式 An ... -
Java RMI
2013-03-28 15:12 1744Java Rmi 目录 1 JAVA RMI 1 ... -
java内部类
2013-03-19 16:25 1068Java内部类 目录 1 JAVA ... -
java多线程设计模式之订单模式
2013-03-11 14:00 2717Java多线程实现订单模式: 客户端线程向服务端发起请求后, ... -
java多线程设计模式之线程池处理请求
2013-03-08 17:50 1829Java实现线程池处理请求: 客户端线程发出请求,请求存入请 ... -
java多线程设计模式之异步处理请求
2013-03-08 12:36 4530Java实现多线程异步处理请求: Java实现多线程异步处理 ... -
java多线程设计模式之读写文件模式
2013-03-07 17:56 1608Java实现多线程读写数据 ... -
java多线程设计模式之生产者与消费者
2013-03-07 11:34 1081Java实现多线程生产者与消费者: 生产者线程负责生产产品 ... -
java多线程设计模式之文件保存
2013-03-06 16:16 1631Java实现多线程保存文件:两线程去保存文件,一个保存线程定时 ... -
java多线程设计模式之队列通信
2013-03-06 13:51 2519Java实现多线程处理队列请求通信:客户端线程向请求队列中不断 ... -
Java读linux系统文件文件名乱码
2012-12-06 17:01 91841,问题描述 web应用想通过Java读取linux系统文件显 ... -
Java安全加密
2012-11-28 10:24 2004安全加密 目录 1 加密安全 1 1.1 应用的安全 1 ... -
图着色问题
2012-11-27 13:05 3150图着色问题 目录 1 图 ... -
JDK6新特性
2012-07-03 23:24 2906JDK6的新特性 JDK6的新特性之一_Desktop类 ... -
JDK7新特性
2012-07-03 15:39 3533JDK7新特性 一 JDK7新特性简介 准备 JDK7下载 ... -
JDK5新特性
2012-07-03 10:23 73JDK5.0新特性 1.自动封箱和自动解封(简单类型和封装类 ... -
java多线程
2012-06-15 15:12 1585Java多线程 目录 1 线 ... -
代理模式
2012-06-13 14:12 1399代理模式 目录 1 代理 ... -
java垃圾回收机制
2012-06-11 11:30 2569Java内存回收 目录 1 JAVA内存STACK和HE ...
相关推荐
此装饰器将备注应用于类的方法。 用法 将装饰器应用于类的方法。 缓存是该方法的本地缓存,但在该类的所有实例之间共享。 强烈建议您仅在纯方法上使用此装饰器。 安装: npm i memo-decorator --save 配置 export ...
11. MEMO(备注):用于记录关于书籍的其他信息,如简介、评论等,VARCHAR2(100)可变长度字符串。 出售信息表记录了每笔销售交易的细节: 1. SELLTIME(销售时间):交易发生的时间,NOT NULL的DATE类型。 2. ISBN...
在数据库操作中,某些字段类型如备注型(Memo)不支持排序,而文本型、数字型和自动编号型则可以;在.NET框架中,验证控件如`CompareValidator`和`RequiredFieldValidator`组合使用可以验证TextBox控件输入的年龄...
和科目备注 Memo。 五、实践示例 例如,在 AG1、AG2 和 AG3 中,用户可以配置不同的科目分配规则,例如根据不同的 valuation class 配置不同的价差科目。在跨公司库存转移时可能会加上运输费等,用户可以给某类 ...
1. **数据库建表**:首先,需要在SQL Server中创建一个名为`student`的表,并定义相应的字段,如`学号(sno)`、`姓名(sname)`、`密码(password)`和`备注(memo)`。 - **SQL语句示例**: ```sql CREATE TABLE ...
- **备注** (`memo`):用于存储关于学生的额外信息。 可以通过以下SQL命令创建这个表: ```sql CREATE TABLE student ( sno INT PRIMARY KEY, sname VARCHAR(50), password VARCHAR(50), memo VARCHAR(255) );...
<ecs:column property="memo" title="备注"/> ``` #### 五、总结 通过上述步骤,我们可以看到ECSide极大地简化了Web应用中列表数据的展示过程。它不仅提高了开发效率,还使得页面的布局更加灵活。对于初学者来...
appId=09999988&actionType=toAccount&goBack=NO&amount=1.00&userId=2088501156491651&memo=备注2088501156491651 具体的链接:alipays://platformapi/startapp?appId=09999988&actionType=toAccount&goBack=NO&...
G_SpecialityInfo 表格用于记录专业信息,包含专业代码(SpecialityID)、专业名称(SpecialityName)、学年(StudyYear)和备注(Memo)。专业代码是主键。 G_CourseInfo 表格存储课程信息,包括课程代码...
备注:<input type="text" name="memo"> 新增"/> ``` ##### 2. 数据库连接与操作 在`insdataok.jsp`页面中,我们首先建立与数据库的连接,然后根据用户提交的数据执行SQL插入语句。 **数据库连接代码示例...
13. 备注字段(Memo Field)通常不能用于建立索引,因为它们通常包含长文本,不适合快速查找。 14. 表格式窗体可以同时显示多条记录,适合于浏览和编辑大量数据。 15. 在UDP通信中,使用DatagramPacket的...
- `memo`: 备注信息。 - **文件类别数据库(type_file)**:用于定义文件的类别。 - 字段: - `Number`: 文件编号。 - `File_name`: 文件名称。 - `File_blob`: 文件内容。 - `File_class`: 文件所属类别。...
12. DOCTOR_MEMO: 医生说明,用于记录医生对医嘱的额外指示或备注。 13. RELATION_KEY: 医嘱关联的唯一号,可能关联到其他统计信息。 14. PRICE: 医嘱的价格,以货币形式表示。 15. CTRL_INFO: 医嘱控制信息,...
27. **排序字段数据类型**:备注型字段(Memo Field)通常不支持直接的排序操作,因为它们通常包含较长的文本或富文本内容。 28. **数据库记录指针**:在数据库操作中,可以通过SQL命令或特定API相对移动或绝对移动...
- 表中的字段类型包括文本(Text)、日期(Date)和备注(Memo),但不包括索引(Index),索引是用于加速查询的数据结构。 2. 操作系统概念: - 计算机操作系统的主要功能是管理计算机系统的软硬件资源,提高...
备注:("memo")%> } } else { System.out.println("连接数据库失败!"); } %> 更新数据</a><br/> 增加数据</a><br/> 删除数据</a><br/> ``` #### 四、总结 本篇示例代码展示了如何在JSP页面中...
- `memo`: 描述备注。 - `url`: 对应URL路径。 - `priority`: 权限优先级。 - `type`: 权限类型。 - `name`: 权限编码。 - `id`: 自增长主键。 5. **角色_资源表 (`roles_resources`)**: - `rsid`: 资源表...
17. Access索引:备注型字段(Memo Field)在Access中无法建立索引,不利于快速查找。 18. Web浏览:要访问某个公司的主页,需要知道该公司的WWW地址,即网址。 19. ASP.NET验证控件:ASP.NET提供了多种验证控件,...
14. 表字段类型:表字段通常包括文本(Text)、日期(Date)、备注(Memo)等,索引(Index)不是字段类型,而是用于提高查询效率的结构。 15. 关系数据库记录顺序:关系数据库中的记录没有固定的前后顺序,可以...