J-Hi的生成器到底生成了些什么?
自J-Hi正式发布以来(2011-1-14)已有三百多个爱好者加入我们的交流群,下载次数约1300次。随着使用者的增加逐渐增多,大家在使用中的疑问也越来越多。其中最多的问题就是生成器到底生成了些什么东西,下面以xxx服务,实体***为例,对生成的文件一一讲解:
数据库相关
对应不同的数据库J-Hi会生成不同的数据库脚本文件,生成的文件会临时存放在web/db目录下的相关数据库(MSSQL/MYSQL/ORACLE)子目录下,每次生成该目录下的文件都会清理一次。生成的文件如下:
xxx.sql 定义该服务下所有实体(枚举实体除外)的数据库表的创建
xxx_BaseData.sql用于对该服务下的实体,为系统表插入相关数据,系统表包括:菜单、权限、枚举等,通过该文件会将与实体相关的菜单信息,权限信息等一次性的插入到系统表中
Java相关
因为Java含盖的框架有很多,采用不同的框架不同的技术生成的内容会有所不同,下面让我们按三层结构的原理划分说明:
数据访问层
xxx.dao包为数据访问层的总包,对应不同的ORM框架还会有相应的子包,比如hibernate、ibatis(ibatis2)、ibatis3等子包。
***DAO.java:在dao包下这是个接口,用于规范不同框架之间的差异。
hibernate子包:
***DAOHibernate.java:hibernate数据访问的具体实现类,该类继承BaseDAOHibernate,从而实现对hibernate的封装
***.hbm.xml:该文件是hibernate的映射文件
我们之所以把ibatis的两个不同版本分两个子包来管理,是因为ibatis2与ibatis3在底层实现上已经有很大的差异,无论是内部运行原理还是配置文件基本上是颠覆性的变化。
ibatis子包
***DAOIbatis.java:ibatis2数据访问的具实体现类,该类继承BaseDAOIbatis,从而实现对Ibatis2的封装
***.ism.xml:ibatis2的映射文件,之所以后缀叫ism是指ibatis sql mapping
ibatis3子包
***DAOIbatis3.java:ibatis3数据访问的具实体现类,该类继承BaseDAOIbatis,从而实现对Ibatis3的封装
***.ism3.xml:ibatis3的映射文件,之所以后缀叫ism是指ibatis3 sql mapping
业务逻辑层
业务逻辑层J-Hi采用的是spring,因此大体上与spring的标准结构完全相同
xxx.service包为业务逻辑层的总包,接口定义在该包下
***Manager.java:业务逻辑的接口类文件,缺省生成的是实体的增删查改方法,如果在业务逻辑层中想做权限控制,可以调用*Security***()方法
xxx.service.impl包下的
***ManagerImpl.java:是业务逻辑的具体类,该类继承ManagerImpl类。如果是特定的业务逻辑一定要在该类中通过手写代码的形式实现之
appContext-xxx.xml:是spring的配置文件,放在置在xxx包下
表现层
xxx.action包为表现层的总包,对应不同的表现层框架会有相应的子包,比如webwork、struts等子包。
***PageInfo.java:在action总包下,该类是与框架无关的,实际上该类记录页面信息的一个POJO,信息主要包括三部分:1)翻页(page):行数、当前页数等;2)过滤器(filter):即查询条件;3)排序器(sorter):即正序倒序
webwork子包:
***ListAction.java:查询页面时所调用的动作
***.RemoveActoin.java:删除记录时所调用的动作
***.RemoveAllActoin.java:批量删除时所调用的动作
***SaveAction.java:保存记录时所调用的动作
***.ViewAllActoin.java:查看记录时所调用的动作
xwork-xxx.xml:webwork的配置文件
与webwork相比,struts的类文件只有一个,所以的动作都是通过方法命名调用实现的,我们之所以做成两种生成方式,是想考虑用户会有个自不同的编程偏好,从而我们为些在不同框架间提供两种生成模式,以适应这种编程偏好的差异
struts子包:
平台目前舍弃了对struts1.x的支持,所以与struts相关都是以struts2为前提的
***Action.java:该Action包括了所有的页面调用动作,通过方法命名进行调度
struts-xxx.xml:struts2的配置文件
POJO及其它
在xxx.model包为POJO的总包,一个POJO实际上是由两个类文件组成的,即
***Abstract.java:该类是POJO的抽象类
***.java:该类是POJO的具体类
之所以这样做是为了避免手写的代码会被生成器生成的文件所覆盖
***.java:如果在定义是有枚举实体,在model包下还有会生对应枚举实体的常量类文件
***-conversion.properties:如果实体有从实体,也就是主从结构,生成器对应主实体生成该文件,其目的是为了适应表现层框架对页面信息的对象化封装
xxx--security.properties:该文件放置在xxx包下,是权限的映射信息的配置文件
页面相关
以后生成器会根据所选模版不同,而对应生成的页面会有很大差异,现在以目前平台的经典模版为例
***List.jsp:查询页面
***Edit.jsp:编辑页面
***View.jsp:查看页面
***.js:与JSP文件应对应的javascript文件
源数据相关
***.hsc.xml 对应每个服务,平台在WEB-INF/matadate目录下都会生成一个源数据的描述文件。该文件记录了定义了模型的全部信息。hsc的意义为:hi service config
基于平台生成器避免手动代码被覆盖的解决方案
如果您采用本平台开发,理论上80%以上的代码都是生成出来的。这样就带来了一个新问题—如何保证我手动改写或添加的代码不会被生成器生成的文件所覆盖?
考虑到上述问题生成器在生成文件时有如下规则:
生成器会反复生成并覆盖以下类与文件:
i. model.original包下的抽象类
ii. action包下***PageInfo类
iii. model包下的***.hbm.xml文件
iv. 服务根包下的appContext-***.xml文件
v. 服务根包下的***-security.properties文件
vi. src根下的xwork-***.xml文件
除上述文件外,生成器对生成其它文件时均会判断是否以存在,如果存生就不再生成也不会覆盖已生成或手动修改类或配置文件的内容
从反复生成的文件规则上可以看出,生成器只会反复生成:
1) 与实体属性密切相关的类或配置文件如模型的抽象类与***PageInfo、***.hbm.xml,因为实体中的属性名称或数量发生变化,生成器要适应对实体属性的变化
2) 与整个服务相关的配置文件如xwork-***.xml、appContext-***.xml等等,因为一个服务下会有多个实体,生成器要适应服务下实体数据库的增减
3) 对于那些与实体相关并且不与服务或实体属性相关的类生成器却只会生成一次如dao、service、action下的所有类,以保证您手写的代码不会被生成器所覆盖
在基于平台开发时,因采用生成器生成所以可以使用如下解决方案来避免您手写的代码或配置不会被生成器所覆盖
i. 如果您要对模型类实现某个接口或方法,请改写model包下的具体类,该类只会生成一次,注意千万不要修改original包下抽象中的内容
ii. 如果您要对表现层的配置文件做修改,以xwork-test.xml为例,操作应该是1)新建一个xwork-test-customer.xml配置文件,2)将您要修改或要增加的actoin写在该文件中(即使action名与xwork-test.xml只的action名重复也没有关系,系统会以您的action为最高优先级),3)在xwork.xml文件中引入该配置文件注意一定要放在xwork-customer.xml引用的下面。只有这样复名的action才会优先调用您的配置