常规功能和模块自定义系统 (cfcmms)—014模块自定义概述(1)
前面的章节讲了一些搭建系统和Extjs6的一些相关内容,这节开始介绍一下《常规功能和模块自定义系统》中的模块自定义的部分。
本系统从最终的结果来看,其实就是给数据库做了一个在浏览器中可操作、可查询的界面。数据库中的表对应于模块,表中的字段也对应于本系统中的模块字段,表间的约束关系根据字段属性设置来定义。对于普通的管理系统而言,必定能将其数据结构按照关系数据库的范式来进行设计。模块之间的分层清晰,没有循环引用和网状数据,这也是本系统能够处理数据库的基本要求。
系统中最基本的元素就是模块及字段,其他所有的附加和延伸功能都是在这二个元素的基础上扩展的。
首先我们来对模块做一个定义。一个模块就是对数据库中的一张表(table)、一个查询(query)、存贮过程或者一条sql语句的总体描述,可以用模块名称、模块类型来描述具体信息。对于一个模块的属性字段我能想到的设置见下图(以后可根据实际需要增加新的模块属性字段):
每个模块的属性定义数据也是放在数据库的表中,表名为_Module,java bean为_Module.java,在com.jfok.cfcmms.hibernate.system.module的包下面。本系统中的系统表的维护和用户表的维护是一样的。
下面是_Module.java的定义的一部分:
@TableDefine(group = "系统模块", id = 9902, title = "系统模块")
public class _Module implements _IModuleControlInterface, Serializable {
@Id
@FieldDefine(title = "模块ID号", number = 10, fieldGroup = "基本信息")
@Column(nullable = false, length = 10)
private String tf_moduleId; // 模块ID,模块序号
@JsonIgnore
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
@JoinColumn(name = "tf_moduleGroupId", nullable = false)
@FieldDefine(title = "模块分组", number = 20, fieldGroup = "基本信息")
private _ModuleGroup tf_ModuleGroup;
@FieldDefine(title = "模块标识", number = 30, fieldGroup = "基本信息")
@Column(nullable = false, length = 50, updatable = false)
private String tf_moduleName; // 模块英文名称
@FieldDefine(title = "模块名称", nameField = true, number = 40, fieldGroup = "基本信息")
@Column(nullable = false, length = 50)
private String tf_title; // 模块中文名称
@FieldDefine(title = "模块简称", number = 50, fieldGroup = "基本信息")
@Column(length = 20)
private String tf_shortname; // 简称
@FieldDefine(title = "英文简称", number = 60, fieldGroup = "基本信息")
@Column(length = 20)
private String tf_englishname; // 英文简称,在新增序号的时候,可以把这字母加进去
@FieldDefine(title = "表名", number = 70, fieldGroup = "基本信息")
@Column(length = 50)
private String tf_tableName;
在类的上面有一个自定义的标注TableDefine,里面定义了这个模块的一些主要属性。这个功能主要是用于导入模块而设置的,在你设计好一个用户模块以后,可以在模块上面和字段上面加上自定义的标注语句,然后就可以将模块导入到系统里面,标注信息会自动的加进去。
上面这个TableDefine的的部分定义如下:
@Retention(RetentionPolicy.RUNTIME)
/**
* 定义在模块bean类上的标注,用来描述该模块的各种属性。
*
* (在该bean属性导入到数据库以后,标注的信息将会失效,最终的各种属性值以数据库中的为准)
*
* 系统中存放所有模块信息的表为 _Module(所有以_开头的表都是系统表,请业务表不要加此下划线)
*
* @author jiangfeng
*
*/
public @interface TableDefine {
/**
*
* 模块的唯一标识符,默认是该类的类名,在将模块属性导入到数据库中时自动使用类名。
*
* (整个系统中不允许有相同的hibernate bean类名,哪怕是在不同的package中也不能有相同的类名。
*
* moduleName
*
*/
/**
* 模块的id号,为一个6位数字,用来代表一个唯一的模块,在生成查询语句的时候,用 _t{id} 来表示此表的别名
*
* @return
*/
int id();
/**
* 如果在数据库中使用的表或视图和此bean的名称不一致,需要设置tableName ,在生成sql语句的时候,会用此
* tableName的值来作为table名。
*
* 如果一致,则不用设置此字段。
*
* @return
*/
String tableName() default "";
/**
* 此模块的具体名称描述,用来显示在window,panel中的title部分
*
* @return
*/
String title();
一般情况下,类名和数据库中的表名(视图名)是一一对应的,当然也可以设置别名。模块只有一个父级的约束,就是模块分组。
一个中小型的的管理系统一般有几十个模块,再加上系统模块就要超过一百多了了。因此为了管理方便,需要对模块进行一下分组。因此又要建立一个_ModuleGroup的模块。java bean文件如下:
package com.jfok.cfcmms.hibernate.system.module;
import ......
/**
* 模块分组,每一个module都被分配到了一个组中,组是分级的,每个模块必须放在最末级的分组上。
*
* 暂定分级为2,2,2即最大可分成3级,每级2位代码
*
* @author jfok 2012.11.7
*/
@SuppressWarnings("serial")
@Entity
@JsonSerialize(include = JsonSerialize.Inclusion.NON_EMPTY)
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@TableDefine(group = "系统模块", id = 9901, title = "模块分组", codeLevel = "2,2,2",
isSystem = true, defaultOrderField = "tf_moduleGroupId")
public class _ModuleGroup implements _IModuleControlInterface, Serializable {
public static final String TITLE = "tf_title";
@Id
@FieldDefine(title = "模块分组编码", number = 10)
@Column(nullable = false, length = 10)
private String tf_moduleGroupId;
@FieldDefine(title = "父节点编码", hidden = true, number = 15)
private String tf_pid;
@FieldDefine(title = "模块分组名称", nameField = true, number = 20)
@Column(nullable = false, length = 50, unique = true)
private String tf_title;
@FieldDefine(title = "系统组", number = 30)
private Boolean tf_isSystemGroup;
@FieldDefine(title = "描述", number = 40)
@Column(length = 50)
private String tf_description;
@FieldDefine(title = "图标Cls", number = 50)
@Column(length = 50)
private String tf_iconCls;
@FieldDefine(title = "图标地址", number = 60)
@Column(length = 50)
private String tf_iconUrl;
@JsonIgnore
@FieldDefine(title = "图标文件", number = 70)
@Column(length = 50)
private Blob tf_iconFile;
@FieldDefine(title = "备注", number = 190)
private String tf_remark;
在_Module中有一个ManyToOne的标注
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
@JoinColumn(name = "tf_moduleGroupId", nullable = false)
@FieldDefine(title = "模块分组", number = 20, fieldGroup = "基本信息")
private _ModuleGroup tf_ModuleGroup;
表明_ModuleGroup是_Module的一个父模块。在新增一个模块的时候,必须选择一个模块分组。然后能够在我的这个系统里看到的最直接的就是父模块可以作为子模块的导航列表。如下图,可以根据模块分组来显示相应的模块。