《易道客》源码剖析之二:模块的定义和使用
2013-02-19 20:58
281 查看
一、简介
此处的模块,指的是逻辑模块,一个物理模块(参见:模块的目录结构分析)可以包含多个逻辑模块。可以将某一功能定义成一个逻辑模块,一个逻辑模块可以被一个或多个菜单引用。
二、模块定义的相关实现类。
1、相关类:
(1)/common/module/Module.java 模块类:定义一个模块,如:我的客户模块、联系人模块等。
(2)/common/module/Operation.java 操作类:定义一个模块包含的操作,如增加、修改等。
(3)/common/module/ModuleGroup.java 模块分组类:用于将模块分类管理。
(4)/common/module/ModuleFactory.java 模块工厂接口,定义一个模块时,需要实现该接口。
(5)/common/module/ModuleFere.java 模块伴侣类:用于模块的注册和管理。
(6)/kh/main/jk/module/ModuleFactory_myClient.java “我的客户”模块定义,实现了ModuleFactory接口,用于产生“我的客户”模块。
2、前五个类定义在公共区域内,是整个系统功能模块化实现的类。第六个类是我的客户模块定义的一个例子,当我们开发一个新的功能模块时,就可以像ModuleFactory_myClient.java一样,定义一个模块。之后还需要在ModuleFere内将该模块注册发布,这样该模块就可以被各个菜单所引用。
3、前五个类只是普通的java类,而非bo对象。也就是说,一个模块的具体定义,是写死的程序代码中的(如:我的客户模块的定义,在ModuleFactory_myClient.java中),而不是存放在数据库中。之所以这么做,是考虑到模块的高内聚。如果存在数据库内,模块的本身代码和模块的定义就会分开,前者是在某个文件夹下面(/kh/main/),后面在数据库中,这样如果将某个模块从一个系统copy至别个系统中使用时,还在重新在另一个数据库内定义该模块,很不方便。(之前的系统框架曾是将Module、Operation、ModuleGroup对象存放在DB中,后面感觉不好,改成现在这样子。)
4、一个新模块的定义和注册方式。当编写一个新的功能模块时,需要在模块内的jk\module\文件夹下面,建立一个新的模块定义类,如ModuleFactory_myClient.java,具体可参见该类的代码。然后注册时,先确认该模块放在哪个模块分组中,然后在ModuleFere.java类中,先找到该模块分组处,添加如下几行代码。
三、重要代码分析
1、Module.java
Java代码
public class Module
{
private String id;//标识
private String name; //名称
private String rukouUrl; //入口链接
private String verSm;//版本说明
private int verNum = 1; //支持版本数(增加‘操作’时对‘适用版本’项的控制)
private List<Operation> operations;//可以进行的操作
private ModuleGroup moduleGroup;//所属分组
public Module(String id, String name, int verNum, String rukouUrl)
{
super();
this.id = id;
this.name = name;
this.rukouUrl = rukouUrl;
this.verNum = verNum;
}
......
}
verNum,verSm分别用来说明该模块支持多少个版本,以及不同版本的差异。一个模块可以多个版本,菜单在引用模块时,需要说明以哪个版本号来使用该模块。不同的版本,在使用时,功能会有所差异。系统中各种类型数据(如:客户类别、客户所属区域等)的管理,用的就是一个模块不同的版本号来处理的。UserInfoLogin的nowSelectMenuModuleVer属性,始终记录着当前菜单以哪个版本号来使用当前模块,具体模块间的差异,需要编程实现。除非特殊需要,否则一般模块尽量只用一个版本号,降低程序复杂度,简单的永远是最好的。
2、Operation.java
Java代码
public class Operation
{
private String id;//标识
private String name; //名称
private String classMethod; //此操作所涉及到的类和方法名(如:com.abc.domain.access.action.common.MenuAction.add 其中add是方法名,前面部分为类完整路径),多个之间用
逗号隔开
private String type;//对于同一模块中,不应当出现类型相同的操作
public Operation(String id, String name, String type, String classMethod)
{
super();
this.id = id;
this.name = name;
this.classMethod = classMethod;
this.type = type;
}
......
}
(1)在一个模块内,如增加、修改、删除分别代表三个不同的操作。
(2)classMethod将用于更细粒度的访问控制,在访问每一个action的方法时,都将判断是否有该方法的访问权限,具体可参见权限管理中的说明。
(3)type用于唯一标识一个模块内的某个操作(可以理解为功能按钮),同一模块能,不能出现重复的操作类型。操作类型的定义需要和action中按钮的定义的类型保持一致。此属性也是权限控制时使用,用于控制能否看到某个按钮(如:增加、修改、删除等)。type建议设置值:
01 增加 add
02 修改 update
03 删除 delete
04 详述 view
05 列表 list
11 增加_1 add_1
12 修改_1 update_1
13 删除_1 delete_1
14 详述_1 view_1
15 列表_1 list_1
80 其他 other
81 其他_1 other_1
82 其他_2 other_2
83 其他_3 other_3
3、ModuleFactory_myClient.java
Java代码
public class ModuleFactory_myClient implements ModuleFactory
{
public static String moduleId=""; //模块ID
public Module get(String aModuleId)
{
moduleId=aModuleId;
//模块定义
Module m=new Module(moduleId, "我的客户", 1, "/kh/main/myClient/list.action");
//操作定义
List<Operation> ops=new LinkedList<Operation>();
ops.add(new Operation(moduleId+"_01", "增加", "add", "com.abc.domain.kh.main.inside.action.MyClientAction.add,com.abc.domain.kh.main.inside.action.MyClientAction.addDone"));
ops.add(new Operation(moduleId+"_02", "修改", "update", "com.abc.domain.kh.main.inside.action.MyClientAction.update,com.abc.domain.kh.main.inside.action.MyClientAction.updateDone"));
ops.add(new Operation(moduleId+"_03", "删除", "delete", "com.abc.domain.kh.main.inside.action.MyClientAction.toLaji,com.abc.domain.kh.main.inside.action.MyClientAction.toLajiDone"));
ops.add(new Operation(moduleId+"_04", "类别调整", "other", "com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChange,com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChangeDone"));
ops.add(new Operation(moduleId+"_05", "增加联系人", "add_1", "com.abc.domain.kh.main.inside.action.MyClientAction.addOne,com.abc.domain.kh.main.inside.action.MyClientAction.addOneDone"));
ops.add(new Operation(moduleId+"_06", "修改联系人", "update_1", "com.abc.domain.kh.main.inside.action.MyClientAction.updateOne,com.abc.domain.kh.main.inside.action.MyClientAction.updateOneDone"));
ops.add(new Operation(moduleId+"_07", "删除联系人", "delete_1", "com.abc.domain.kh.main.inside.action.MyClientAction.deleteOne"));
ops.add(new Operation(moduleId+"_08", "设置主联系人", "setMain", "com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkman,com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkmanDone"));
ops.add(new Operation(moduleId+"_09", "客户记事", "notepad", "com.abc.domain.kh.main.inside.action.MyClientAction.notepad,com.abc.domain.kh.main.inside.action.MyClientAction.notepadDone"));
//给模块设置操作
m.setOperations(ops);
return m;
}
}
4、ModuleFere.java中的定义如下:
Java代码
//-------------------------------客户分组---------------------------------------
{
String groupId="kh"; //分组ID
String groupName="客户管理"; //分组名称
ModuleGroup group = new ModuleGroup(groupId, groupName);
{//我的客户
ModuleFactory mf=new ModuleFactory_myClient();
String num="_01"; //组内编号
proModule(group,mf,num);
}
......
}
groupId是整个客户管理区域(分组)的编号,所有区域编号不能重复,num是我的客户模块在分组内的编号,一个分组内,num不允许出现重复的值。ModuleFere是模块的注册地方,一个模块编写完成并在此处注册之后,就可以被菜单使用了。
四、模块的使用
1、启动tomcat,在浏览器中打开系统登陆界面,输入用户名devAdmin(注:开发管理员),密码是devAdmin+当前日期,如devAdmin20121226,进入后找到:系统配置—基础配置—菜单管理
2、先创建一个菜单,再修改其引用的模块信息。如下图:
3、用admin进入系统,给用户分配相应的权限即可。
此处的模块,指的是逻辑模块,一个物理模块(参见:模块的目录结构分析)可以包含多个逻辑模块。可以将某一功能定义成一个逻辑模块,一个逻辑模块可以被一个或多个菜单引用。
二、模块定义的相关实现类。
1、相关类:
(1)/common/module/Module.java 模块类:定义一个模块,如:我的客户模块、联系人模块等。
(2)/common/module/Operation.java 操作类:定义一个模块包含的操作,如增加、修改等。
(3)/common/module/ModuleGroup.java 模块分组类:用于将模块分类管理。
(4)/common/module/ModuleFactory.java 模块工厂接口,定义一个模块时,需要实现该接口。
(5)/common/module/ModuleFere.java 模块伴侣类:用于模块的注册和管理。
(6)/kh/main/jk/module/ModuleFactory_myClient.java “我的客户”模块定义,实现了ModuleFactory接口,用于产生“我的客户”模块。
2、前五个类定义在公共区域内,是整个系统功能模块化实现的类。第六个类是我的客户模块定义的一个例子,当我们开发一个新的功能模块时,就可以像ModuleFactory_myClient.java一样,定义一个模块。之后还需要在ModuleFere内将该模块注册发布,这样该模块就可以被各个菜单所引用。
3、前五个类只是普通的java类,而非bo对象。也就是说,一个模块的具体定义,是写死的程序代码中的(如:我的客户模块的定义,在ModuleFactory_myClient.java中),而不是存放在数据库中。之所以这么做,是考虑到模块的高内聚。如果存在数据库内,模块的本身代码和模块的定义就会分开,前者是在某个文件夹下面(/kh/main/),后面在数据库中,这样如果将某个模块从一个系统copy至别个系统中使用时,还在重新在另一个数据库内定义该模块,很不方便。(之前的系统框架曾是将Module、Operation、ModuleGroup对象存放在DB中,后面感觉不好,改成现在这样子。)
4、一个新模块的定义和注册方式。当编写一个新的功能模块时,需要在模块内的jk\module\文件夹下面,建立一个新的模块定义类,如ModuleFactory_myClient.java,具体可参见该类的代码。然后注册时,先确认该模块放在哪个模块分组中,然后在ModuleFere.java类中,先找到该模块分组处,添加如下几行代码。
三、重要代码分析
1、Module.java
Java代码
public class Module
{
private String id;//标识
private String name; //名称
private String rukouUrl; //入口链接
private String verSm;//版本说明
private int verNum = 1; //支持版本数(增加‘操作’时对‘适用版本’项的控制)
private List<Operation> operations;//可以进行的操作
private ModuleGroup moduleGroup;//所属分组
public Module(String id, String name, int verNum, String rukouUrl)
{
super();
this.id = id;
this.name = name;
this.rukouUrl = rukouUrl;
this.verNum = verNum;
}
......
}
public class Module { private String id;//标识 private String name; //名称 private String rukouUrl; //入口链接 private String verSm;//版本说明 private int verNum = 1; //支持版本数(增加‘操作’时对‘适用版本’项的控制) private List<Operation> operations;//可以进行的操作 private ModuleGroup moduleGroup;//所属分组 public Module(String id, String name, int verNum, String rukouUrl) { super(); this.id = id; this.name = name; this.rukouUrl = rukouUrl; this.verNum = verNum; } ...... }
verNum,verSm分别用来说明该模块支持多少个版本,以及不同版本的差异。一个模块可以多个版本,菜单在引用模块时,需要说明以哪个版本号来使用该模块。不同的版本,在使用时,功能会有所差异。系统中各种类型数据(如:客户类别、客户所属区域等)的管理,用的就是一个模块不同的版本号来处理的。UserInfoLogin的nowSelectMenuModuleVer属性,始终记录着当前菜单以哪个版本号来使用当前模块,具体模块间的差异,需要编程实现。除非特殊需要,否则一般模块尽量只用一个版本号,降低程序复杂度,简单的永远是最好的。
2、Operation.java
Java代码
public class Operation
{
private String id;//标识
private String name; //名称
private String classMethod; //此操作所涉及到的类和方法名(如:com.abc.domain.access.action.common.MenuAction.add 其中add是方法名,前面部分为类完整路径),多个之间用
逗号隔开
private String type;//对于同一模块中,不应当出现类型相同的操作
public Operation(String id, String name, String type, String classMethod)
{
super();
this.id = id;
this.name = name;
this.classMethod = classMethod;
this.type = type;
}
......
}
public class Operation{ private String id;//标识 private String name; //名称 private String classMethod; //此操作所涉及到的类和方法名(如:com.abc.domain.access.action.common.MenuAction.add 其中add是方法名,前面部分为类完整路径),多个之间用逗号隔开 private String type;//对于同一模块中,不应当出现类型相同的操作 public Operation(String id, String name, String type, String classMethod) { super(); this.id = id; this.name = name; this.classMethod = classMethod; this.type = type; } ......}
(1)在一个模块内,如增加、修改、删除分别代表三个不同的操作。
(2)classMethod将用于更细粒度的访问控制,在访问每一个action的方法时,都将判断是否有该方法的访问权限,具体可参见权限管理中的说明。
(3)type用于唯一标识一个模块内的某个操作(可以理解为功能按钮),同一模块能,不能出现重复的操作类型。操作类型的定义需要和action中按钮的定义的类型保持一致。此属性也是权限控制时使用,用于控制能否看到某个按钮(如:增加、修改、删除等)。type建议设置值:
01 增加 add
02 修改 update
03 删除 delete
04 详述 view
05 列表 list
11 增加_1 add_1
12 修改_1 update_1
13 删除_1 delete_1
14 详述_1 view_1
15 列表_1 list_1
80 其他 other
81 其他_1 other_1
82 其他_2 other_2
83 其他_3 other_3
3、ModuleFactory_myClient.java
Java代码
public class ModuleFactory_myClient implements ModuleFactory
{
public static String moduleId=""; //模块ID
public Module get(String aModuleId)
{
moduleId=aModuleId;
//模块定义
Module m=new Module(moduleId, "我的客户", 1, "/kh/main/myClient/list.action");
//操作定义
List<Operation> ops=new LinkedList<Operation>();
ops.add(new Operation(moduleId+"_01", "增加", "add", "com.abc.domain.kh.main.inside.action.MyClientAction.add,com.abc.domain.kh.main.inside.action.MyClientAction.addDone"));
ops.add(new Operation(moduleId+"_02", "修改", "update", "com.abc.domain.kh.main.inside.action.MyClientAction.update,com.abc.domain.kh.main.inside.action.MyClientAction.updateDone"));
ops.add(new Operation(moduleId+"_03", "删除", "delete", "com.abc.domain.kh.main.inside.action.MyClientAction.toLaji,com.abc.domain.kh.main.inside.action.MyClientAction.toLajiDone"));
ops.add(new Operation(moduleId+"_04", "类别调整", "other", "com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChange,com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChangeDone"));
ops.add(new Operation(moduleId+"_05", "增加联系人", "add_1", "com.abc.domain.kh.main.inside.action.MyClientAction.addOne,com.abc.domain.kh.main.inside.action.MyClientAction.addOneDone"));
ops.add(new Operation(moduleId+"_06", "修改联系人", "update_1", "com.abc.domain.kh.main.inside.action.MyClientAction.updateOne,com.abc.domain.kh.main.inside.action.MyClientAction.updateOneDone"));
ops.add(new Operation(moduleId+"_07", "删除联系人", "delete_1", "com.abc.domain.kh.main.inside.action.MyClientAction.deleteOne"));
ops.add(new Operation(moduleId+"_08", "设置主联系人", "setMain", "com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkman,com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkmanDone"));
ops.add(new Operation(moduleId+"_09", "客户记事", "notepad", "com.abc.domain.kh.main.inside.action.MyClientAction.notepad,com.abc.domain.kh.main.inside.action.MyClientAction.notepadDone"));
//给模块设置操作
m.setOperations(ops);
return m;
}
}
public class ModuleFactory_myClient implements ModuleFactory{ public static String moduleId=""; //模块ID public Module get(String aModuleId) { moduleId=aModuleId; //模块定义 Module m=new Module(moduleId, "我的客户", 1, "/kh/main/myClient/list.action"); //操作定义 List<Operation> ops=new LinkedList<Operation>(); ops.add(new Operation(moduleId+"_01", "增加", "add", "com.abc.domain.kh.main.inside.action.MyClientAction.add,com.abc.domain.kh.main.inside.action.MyClientAction.addDone")); ops.add(new Operation(moduleId+"_02", "修改", "update", "com.abc.domain.kh.main.inside.action.MyClientAction.update,com.abc.domain.kh.main.inside.action.MyClientAction.updateDone")); ops.add(new Operation(moduleId+"_03", "删除", "delete", "com.abc.domain.kh.main.inside.action.MyClientAction.toLaji,com.abc.domain.kh.main.inside.action.MyClientAction.toLajiDone")); ops.add(new Operation(moduleId+"_04", "类别调整", "other", "com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChange,com.abc.domain.kh.main.inside.action.MyClientAction.clientSortChangeDone")); ops.add(new Operation(moduleId+"_05", "增加联系人", "add_1", "com.abc.domain.kh.main.inside.action.MyClientAction.addOne,com.abc.domain.kh.main.inside.action.MyClientAction.addOneDone")); ops.add(new Operation(moduleId+"_06", "修改联系人", "update_1", "com.abc.domain.kh.main.inside.action.MyClientAction.updateOne,com.abc.domain.kh.main.inside.action.MyClientAction.updateOneDone")); ops.add(new Operation(moduleId+"_07", "删除联系人", "delete_1", "com.abc.domain.kh.main.inside.action.MyClientAction.deleteOne")); ops.add(new Operation(moduleId+"_08", "设置主联系人", "setMain", "com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkman,com.abc.domain.kh.main.inside.action.MyClientAction.mainLinkmanDone")); ops.add(new Operation(moduleId+"_09", "客户记事", "notepad", "com.abc.domain.kh.main.inside.action.MyClientAction.notepad,com.abc.domain.kh.main.inside.action.MyClientAction.notepadDone")); //给模块设置操作 m.setOperations(ops); return m; }}
4、ModuleFere.java中的定义如下:
Java代码
//-------------------------------客户分组---------------------------------------
{
String groupId="kh"; //分组ID
String groupName="客户管理"; //分组名称
ModuleGroup group = new ModuleGroup(groupId, groupName);
{//我的客户
ModuleFactory mf=new ModuleFactory_myClient();
String num="_01"; //组内编号
proModule(group,mf,num);
}
......
}
//-------------------------------客户分组---------------------------------------{ String groupId="kh"; //分组ID String groupName="客户管理"; //分组名称 ModuleGroup group = new ModuleGroup(groupId, groupName); {//我的客户 ModuleFactory mf=new ModuleFactory_myClient(); String num="_01"; //组内编号 proModule(group,mf,num); } ......}
groupId是整个客户管理区域(分组)的编号,所有区域编号不能重复,num是我的客户模块在分组内的编号,一个分组内,num不允许出现重复的值。ModuleFere是模块的注册地方,一个模块编写完成并在此处注册之后,就可以被菜单使用了。
四、模块的使用
1、启动tomcat,在浏览器中打开系统登陆界面,输入用户名devAdmin(注:开发管理员),密码是devAdmin+当前日期,如devAdmin20121226,进入后找到:系统配置—基础配置—菜单管理
2、先创建一个菜单,再修改其引用的模块信息。如下图:
3、用admin进入系统,给用户分配相应的权限即可。
相关文章推荐
- 《易道客》源码剖析之二:模块的定义和使用
- 《易道客》源码剖析之一:模块的目录结构分析
- 《易道客》源码剖析之一:模块的目录结构分析
- TCMalloc的使用与源码剖析之二---------TCMalloc内存分配与管理简述
- 飘逸的python - 使用dis模块进行代码层次的性能剖析
- requirejs如何使用define定义一个模块
- django使用django.db模块创建表之二
- Node 进阶:express 默认日志组件 morgan 从入门使用到源码剖析
- 玩转Android之Picasso使用详详详详详详解,从入门到源码剖析!!!!
- Linux Framebuffer驱动剖析之二—驱动框架、接口实现和使用
- TCMalloc的使用与源码剖析之一---------TCMalloc 安装和使用
- 使用Jquery+EasyUI 进行框架项目开发案例讲解之二---用户管理源码分享
- 详解Django之admin组件的使用和源码剖析
- GDAL源码剖析(七)之GDAL RasterIO使用说明(续)
- Future和FutureTask使用案例和源码剖析[base jdk8]
- 论坛源码推荐(10.22):使用iOS8 WKWebView的浏览器模块,脉冲动画层
- Webpack-源码一,使用require加载并打包模块
- Python模块定义和使用
- requirejs如何使用define定义一个模块
- 菜单之二:使用xml文件定义菜单 分类: H1_ANDROID 2013-11-03 09:39 1038人阅读 评论(0) 收藏