AEAI DP开发平台精要
1 背景概述
相信很多了解数通畅联软件的人对AEAI DP应用开发平台并不陌生,笔者在入职第一天就开始接触AEAI DP,使用AEAI DP开发过AEAI WM、AEAI CRM以及中国XXXX管理系统项目,在此过程中对AEAI DP有了较为深入了解,工作之余尝试对AEAI DP的工作原理、实际开发工作涉及的技术点进行梳理,希望能够对其他AEAI DP初学者和使用人员有所帮助。
本文相关说明涵盖AEAI DP的远程热部署新特性,AEAI DP V3.5以后版本支持按工程、模块、资源不同粒度实现代码远程增量部署,类似AEAI ESB中的按流程、服务、工程远程热部署模式。
2 预期读者
-
数通畅联内部技术人员
-
外部AEAI DP使用人员
3 技能要求
-
了解Java Web开发过程,熟悉相关知识点
-
对AEAI DP技术手册所涉及的内容熟练掌握
4 架构及原理
4.1 DP产品架构解读
AEAI DP开发平台包括三部分,第一部分是一站式的Java Web框架,在数通畅联软件家族中命名为Hotweb,第二部分基于Eclipse插件的扩展开发设计器,在数通畅联软件家族中命名为Miscdp Studio,第三部分是用于开发调试的服务器HotServer。基于Miscdp Studio可以开发普通Java Web应用、集成Java Web应用,还可以为BPM流程平台开发业务表单及流程相关功能。
Hotweb是一站式的MVCFramework,对前端页面交互及控制层做了统一封装,各类功能模型的交互方式封装在父类中。每个页面提供一个Handler处理Java类和展现JSP页面,一个功能可能涉及多个页面,复用一套业务逻辑处理Service和通用的数据存取持久工具类DAOHelper,在Service层调用通用数据存取类DAOHelper。数据持久层基于IBatis封装,Service层基于Spring来做事务控制和服务配置。
4.2 Howeb交互机制
-
DispatchServlet:前端请求分发,配置于web.xml
-
Handler:具体请求动作处理及控制,调用Service,返回ViewRender
-
Service:后台业务处理,包括接口及实现,Spring配置,通过DaoHelper调用SQLMap
-
SQLMap:负责数据持久化处理(CRUD)
-
ViewRender:前端展现渲染方式定义,实例化PageBean,放置于request的attributes中
-
PageBean:承载前端展现的属性、方法
-
JSP:具体页面代码,使用PageBean来获取handler中设置相关数据。
典型请求页面交互过程模式如下:
-
页面提交发起,一般是post方式至DispatchServlet
Servlet根据HandlerId实例化Handler、根据actionType反射调用对应的处理方法,方法名跟actionType一致
-
Handler处理
在对应方法中,调用Spring配置的Service来存/取数据库
-
根据需要返回不同的ViewRender
如果是ajaxRender直接response返回页面,异步加载或者做相关处理
如果是dispatchRender,一般是转向其他的handler来进行处理
如果是LocalRender,直接调用prepareDisplay来做处理
4.3 典型目录层次结构
如上图:module该目录是放置各模块的代码,每个模块有各自的Handler、Service、SQLMap以及配置文件,这种文件结构模式能够支持AEAI DP实现按模块来部署。
common包里放置的是公共类,controller包里方式放置的框架级handler,cxmodule里面方式的公共service接口和实现类。
4.4 核心配置文件说明
通过AEAI DP平台开发生成相关的配置,下面对核心配置文件进行说明:
4.4.1 web.xml配置
在web.xml中包含filter的定义以及实现
Servlet的定义以及实现
以及Listener
4.4.2 Handler配置
1. HandlerIndex.xml:定义了HandlerId所属的模块,通过Id对应的模块查找对应模块下的映射关系
2. HandlerModule.xml与HandlerContext.xml中均映射关系指向对应的Handler以及JSP。其中HandlerModule.xml中定义的是不同模块下的映射关系而HandlerContext.xml中是公共访问的如主页、左侧功能列表的显示等。
4.4.3 Service 配置
1. ServiceContext.xml中典型配置属性:如数据库、appConfig等;
2. ServiceIndex.xml:通过seviceId所对应的模块去对应模块下的ServiceModule.xml配置文件中查找对应的ServiceImpl以及SqlMap等信息
3. ServiceModule.xml将对应功能模块下的Service层Controller层,用到的java类封装成bean,并通过property指定对应的SqlMap。
4. ServiceContext.xml中,配置了公共调用的Service的实现、配置数据库连接、以及事务控制机制。
4.4.4 DB 相关配置
1. hotweb.properties:配置了数据库的连接信息,如用户名、密码等。
2. SqlMapModule.xml与SqlMapConfig.xml:是sqlmap的索引文件
3. sqlmap:在对应的xml中定义SQl进行数据库操作,sqlMap文件的namespace默认是由表名来生成,在ServcieContext.xml(ServiceModule.xml)中指向业务处理ServiceImpl中
5 开发与部署
5.1 工具设置
5.2 开发步骤
AEAI DP开发平台基于数据库驱动开发,推崇适度需求调研、数据库设计先行、原型驱动的敏捷开发模式。整体过程如下:
1. 通过工程向导创建可运行调试的工程框架,默认预置系统管理功能
2. 设计器向导选择对应的功能模型,来创建功能实例
3. 功能实例配置信息首先通过数据表或SQL来默认生成
4. 在设计器进行特定调整(如:查询条件、显示字段、表单元素、校验控制等)
5. 由代码生成器,生成相关的代码及配置
6. 直接部署运行,查看效果,根据实际需要调整设置,重复4—6步
7. 根据实际需要扩展功能代码、调试。
注意:一旦扩展了代码,就不能再次代码生成,那样会覆盖扩展的代码。
5.2.1 开发约束说明
-
所有的表都需要创建UUID逻辑主键(36位)
-
所有编码类数据在编码管理模块中统一维护
-
如果列表SQL有参数需要解析,必须有“where 1=1”
-
建议开发采用SVN或者CVS进行版本管理
-
如果选择上载资源,则资源关联表,只能三个字段,除了逻辑主键,另外两个字段必须为“BIZ_ID”、“RES_ID”,字段类型都为char(36),建议主键命名为“REF_ID”
6.2.2 跨模块调用说明
在AEAI DP中各个功能模块是彼此隔离的,这里就可能存在跨模块调用问题:
-
跨模块调用handler
不需要做特殊处理,仍然index?SomeHandlerID方式调用跨模块的handler。
-
跨模块调用service
把对应的接口提升到cxmodule包里,可以采用代码重构的方式,选中对应接口类,然后ctrl+shift+v。
-
跨模块调用sqlmap
把sqlmap索引配置迁移公共索引配置(即SqlMapModule.xml中对应配置迁移至SqlMapConfig.xml),模块中的sqlmap文件也对应迁移公共sqlmap目录。
5.2.3 常用Java类清单
5.3 部署方式
双击项目名弹出如下界面,可以修改服务器的地址并修改对应的用户名,连接对应的服务器后部署应用即可。
注意:服务器用户名、密码在Hotserver中有对应的配置,如下图:
在Miscdp Studio对工程中任意目录、文件都可以右键,在右键菜单底部点击“Miscdp资源部署”,如下图:
弹出部署设置窗口,AEAI DP支持三种粒度部署模式:模块、资源、应用。应用就是整个工程,模块指的module目录下的各个package,除了module下的文件,其他都属于资源。可以支持多个模块或者多个资源一起部署,而且内置的部署机制会自动识别,是否要重新加载模块或者重启应用。
5.3.1 按资源部署
在除模块下部署jsp,xml,js,java文件等为资源部署。当部署的内容包含源码时,会默认重启应用
部署的内容不包含源码时默认不会重启应用,且支持同时部署多个资源文件。
5.3.2 按应用部署
在项目名下右键资源部署为部署应用且默认重启应用。
5.3.3 按模块部署
在模块下选择xml、java文件等右键部署资源均为模块部署,默认会重新加载这个模块
注意:在模块的jsp文件夹下右键资源部署(弹出界面如上图)也为模块部署,默认会重新加载部署的模块。但是如果选择是模块jsp文件夹下的jsp文件,则为部署资源,且不用重启应用(jsp是自动编译)。
5.3.4 部署后目录
正常情况下Web应用的所有的classes都在WEB-INF/classes目录下,但基于AEAI DP开发的Web应用部署后有一个特殊目录modules,所有模块里的classes以及对应的配置文件都放置在这个目录里,如下图。
5.4 调试配置
远程调试是复杂业务逻辑的错误定位过程中常用手法,通过调试也可以使程序员对代码脉络更清楚,是程序员必备的技能。AEAI DP 基于Eclipse内置远程机制进行代码调试,具体参见《AEAI DP开发平台技术手册》中的调试配置部分内容。
6 知识点汇总
6.1 分层解读
6.1.1 控制层
对应的Handler如下图:
1. prepareDisplay方法
在handler中默认执行prepareDisplay方法
mergeParam(param)方法中通过handlerId的对比确定需要append的param的信息
storeParam方法在页面间跳转时候,将param存到一个session中,跟mergetParam联合使用保证在页面间切换时候,列表页面的查询条件不丢失。
setAttributes(param)方法中做遍历将param中的值进行set将数据放入到页面中
返回new LocalRenderer(getPage()),在LocalRenderer中的executeRender方法中创建PageBean,所有handler中的属性信息都传入至PageBean中,通过request.setAttribute(PAGE_BEAN_KEY,pageBean)方法将handler信息放入页面所以在JSP中可以通过pageBean中封装的getHandlerURL()获得handlerURL。
2. processPageAttributes方法
processPageAttributes方法用于回调处理扩展属性(下拉框处理、默认值处理)
3. initParameters方法
initParameters方法中可以设置查询条件的默认值
4. getService方法
在getService方法中返回到对应的调用的Service
5. 扩展方法机制说明
方法名与actionType隐藏域变量一致,建议采用@PageActionanotation方式,如果不添加@PageAction,则方法名为do+”actionType”+Action
6.1.2 显示层
顾名思义显示层就是用于前台显示的jsp页面如下图:
1. Page指令
通过Page指令的contentType将页面编码定义为UTF-8
pageEncoding是jsp文件本身的编码
contentType的charset是指服务器发送给客户端时的内容编码
2. Jsp动作
通过jsp在头部useBean在页面引用的javaBean(即pageBean),其中class属性指定类的实例并将其绑定到名由id属性定义的变量上,scope为request,如下:
相关jsp内置方法如下:
jsp:include:在页面被请求的时候引入一个文件。
jsp:useBean:寻找或者实例化一个JavaBean。
jsp:setProperty:设置JavaBean的属性。
jsp:getProperty:输出某个JavaBean的属性。
jsp:forward:把请求转到一个新的页面。
jsp:plugin:根据浏览器类型为Java插件生成OBJECT或EMBED标记
3. Jsp表单
一般情况下页面均会包含一个表id为form1,且内部有一个隐藏域actionType在表单提交时需要赋值。
一般情况下明细表单除了actionType以外还会包含一个operaType隐藏域,用来区分当前操作的状态是insert还是 update。
在form表单中action动作指令通过pageBean.getHandlerURL()获得handler指定跳转的路径,method="post"提交方式为post
4. 资源文件
在Jsp页面中引入通用的资源文件:
<%@include file="/jsp/inc/resource.inc.jsp"%>在该页面中包括常用的javascript及css
在script中定义页面处理的JS,也可以直接引用封装与于Util.js中常见的页面校验(非空、长度等)、请求方法(doDelete、doSubmit)等
util.js中封装了常用js方法如:
style.css为最常用css,其中定义form、table、tr、td样式以及按钮的图标样式等
6.1.3 服务层
后台业务逻辑生成接口与实现类如下图:
后台业务逻辑都生成接口与实现类,都在ServiceContext.xml(ServiceModule.xml)中配置。在实现类中定义对数据库的操作
1. 继承关系说明
每个功能模型都有自己的父类和接口,继承关系如下图所示:
2. processDataType
根据数据表的元数据来转换处理表单传过来的数据,可以扩展设置类型转换器,类型转换器扩展设置在ServiceContext.xml或者ServiceModule.xml中配置,BaseService中对应代码如下:
3. processPrimaryKeys
处理主键默认生成机制,AEAI DP中默认是使用uuid来作为主键的,其实框架层面还支持自增字段主键机制。
6.2 重点技术
6.2.1 常用方法
1. 在PageBean中封装了常见的页面中获取值的方法,如下:
2. 根据需要返回不同的ViewRender,一般情况下为:AjaxRender、DispatchRender、RedirectRenderer、LocalRender
1) AjaxRender:直接response返回值页面,异步加载或者做相关处理
2) DispatchRender:一般是转向其他Handler来进行处理,页面跳转传递request和response可以支持跳转到第三方按Backspace可以返回
3) RedirectRenderer:也是转向其他Handler但不能传递request和response
4) LocalRender:显示 JSP页面
3. DateUtil类中预置许多关于日期处理的方法,例如:日期的格式化,日期的计算,获得当月、当年的第一天等等。
4. 主键生成
调用KeyGenerator.instance().genKey()来自动生成主键ID
5. 加密解密
通过CryptionUtil中的加密解密方法进行加密解密
-
加密方法encryption("root", "12345678");其中root为需要加密的明文、”12345678”为加密的KEY。
-
解密方法decryption(secretData, secretKey);
6. 在User类中预置了许多关于User的跟角色、群组关联属性等
-
可以通过User user = (User) this.getUser()获取User对象
-
并同user对象打点调用不同的方法获得User与角色和群组关联的属性
7. Dataparam转换
-
DataRow调用row.toDataParam();
-
List调用ListUtil.toParamList(records,srcKeys, replaceKeys)
8. StringUtil字符串辅助类
agileai_common的jar包中内置了很多辅助类,如StringUtil,DataUtil,ListUtil、DBUtil等。
9. ListUtil类转换方法
预置许多List转换方法如listToMap()、toXML()、toDataSet()、toParamList()
10. PopupBox.js中封装基于div+iframe的弹出框
Js中使用PopupBox方法时需要将对应的var写在方法的外面,每次调用使用的都是同一个弹出框,写在方法内部时每次调用方法都会新生成一个弹出框。
11. 内置Ajax处理方式
functionpostRequest(form,params)
functionsendRequest(targetUrl,params)
第一种是post方式,第二种是get方式。
6.2.2 授权配置
1. 功能授权
系统预置功能可以设置功能目录、功能节点授权,而且可以授权给角色、群组、人员。
注意:
-
如果授权子节点,则父节点必然会授权。
-
如果只授权到父节点,子节点没有被任何角色、群组、人员,则可以访问父节点下的所有功能节点。
-
如果子节点已被其他的角色(群组、人员)授权,则必须要对这些子节点进行授权,而不能通过授权到父节点的方式来授权子节点。
2. 操作授权
-
通过jsp引入标签按钮配置授权
-
通过状态、角色控制权限
参见《AEAI DP按钮权限配置说明》,http://my.oschina.net/agileai/blog/533385。
6.2.3 典型场景
1. 复制数据插入
1) 把原结果集查询出来,类型为List<DataRow>;
2) 使用ListUtil.toDataParam方法把结果集转换为参数集合,类型为List<DataParam>;
3) 使用DaoHelper调用sqlmap中配置的insertSQL来插入参数集合。
2. 排序控制说明
首先在JSP页面,添加按钮
调用的JS方法如下
上移下移在handler里的方法
在service方法里调整两个字段排序顺序
2. 结果集转换为FormSelect
在进行开发的时候,会遇到select下拉框形式 的表单元素,这时就需要在控制层的pricessPageAttributes方法中将查询得到的结果集转换为formselect类型,如下例:
首先通过查询得到list结果集records,结果集中需要存在有id(编码)和value(值)两列属性
然后new一个FormSelect类型的变量,然后给这个变量添加对应的id和value两个属性字段,再通过putValues方法把结果集中的数据放到formSelect中。在setAttribute中将param中对应的变量的值通过formSelect将这个选中的值存入到变量pcName中。
3. 基于HTML导出Word、PDF
1) 构造Html模板
2) 将模板转换为IO流
3) 调用对应的API进行格式转换
4. 批量处理结果集
首先需要前台jsp页面添加checkbox复选框,代码如下:
上面个代码选中了当前记录的ID,然后点击操作按钮调用对应的JS方法,将ids传到后台handler中处理:
由于接到的参数为多条记录,并用逗号分隔的,需要在后台进行处理,具体代码如下:
5. 数值公式计算
我们在项目使用MVL的TemplateRuntime计算方式,具体代码如下:
输出后的结果:
6. 后台控制jsp页面<td>标签合并
在显示列表页面时,调用下面代码
6.3 学习技巧
6.3.1 利用system代码
使用AEAI DP创建工程的时候默认就会创建系统管理相关代码,系统管理里面涉及的模块几乎是所有管理系统都带的功能,这部分代码较多,值得推荐学习,事实上很多开发所需要的代码样例都可以在里面找到。
6.3.2 跟踪研读父类
Hotweb预置很多典型的功能模型,每个Handler和Service都继承对应功能模型的Handler和Service,而且hotweb源码都直接打入hotweb_core.jar,在开发、调试过程中可以跟踪研究父类来深入掌握相关调用机制、借鉴相关代码技巧。
6.3.3 查找类似代码
很多js代码、工具类的调用方式其实都散落在系统框架(预置的以及自动生成)的代码里,可以通过DP Studio(Eclipse)的文件查找方式来了解相关调用机制。
6.3.4 反编译参考代码
在hotweb中也引用了一些地方类库,如:ecside、ibatis、spring、mvel等等,包括AEAI Portal、AEAI BPM的一些classes、jar文件,都可以通过jd-gui来反编译学习分析代码,参考样例,如:反编译预置的portlet代码、参考开发新portlet。
7 感悟与收获
AEAI DP开发平台可以快速上手,对于最开始入职的我较容易产生成就感,但是随着后续深入使用,实际应用过程中的各种扩展开发,逐渐暴露出我自己的知识积累不足,同时也发现Miscdp Studio可以生成典型功能、典型的方法,便于调试部署,但更多代码的精华是藏在Hotweb框架里,Hotweb预留很多方法用于扩展,预置很多工具类通过组合使用可以几乎所有场景的功能,同时第三方的类库也很容易在AEAI DP中调用来满足实际项目的特定需求。
AEAI DP开发平台精要文档 下载
上一篇: AEAI DP开发平台升级说明
下一篇: 为什么你有时看起来很傻