NC-UAP客户化开发-NC基础技术
本章将介绍NC-UAP平台的技术结构,开发模型,并通过一个例子亲身感受远程接口开发
NC开发基本概念
单据:比如报销时的报销单,一般由表头和表体组成(有些时候还含有表尾)。表头中包含了单据的主信息,比如日期、部门、预算项目;表体包含了单据的明细信息,比如具体的事项和金额。
单据类型:一个业务系统为了使结构更清晰,通常也是分层的。比如,供应链系统包含了采购、库存等子系统,每个子系统都具有一个系统类型,而每个子系统都会有很多张单据,为了区分这些单据,为每张单据命名一个单据类型,作为唯一标识。
模板:单据开发涉及到三大模板(单据模板、查询模板、打印模板)。单据模板定义了单据的显示外观和基本框架,查询模板定义了单据的查询对话框,打印模板定义了单据信息打印到打印机的样式和格式。
VO是ValueObject的简写,在NC中是一个抽象类,它实现了Cloneable和Serializable接口,是NC业务数据的载体在系统各层之间传递业务数据。
CircularlyAccessibleValueObject是ValueObject的子类,提供了对自身的属性进行存取操作的方法。
SuperVO是CircularlyAccessibleValueObject的子类,是NC系统中最常使用的VO类型,它与一张数据库表对应,可以方便的利用NC的JDBCFramework进行持久化操作。
AggregatedValueObject(聚合VO)就是用于存储一对多关系的主子表数据。对于一主多子的情况,实现IExAggVO接口。
UI工厂:虽然能通过三大模板定义出单据的显示,但每张单据都有一些公共的或特殊的行为。UI工厂是一种单据开发框架,它将常用单据抽象成了很多类型,因此,UI工厂相当于是单据开发的代码模板,预置了单据的各种公共行为,比如增、删、改、查,并且可以连接到NC流程平台,支持审批、单据驱动等应用。
远程接口:V5远程组件开发都是基于接口(替代原先的BO访问),访问也都是基于接口。
参照:是一种辅助的数据输入方式,通常弹出界面的形式提供可以参考的数据,比如在录入省份信息时,提供一个全国省份列表以供选择。单据开发中,有很多输入字段存在类似的需求。NC系统中预置了很多种常见参照(基本覆盖了所有的基本档案,比如人员参照,存货参照),如果要自定义一种参照,则需要简单的开发工作。
ToftPanel:提供对NC产品功能节点开发的支持,统一功能节点的注册类型(ToftPanel)。提供了节点开发过程中按钮的注册机制以及按钮与界面的互动机制(通过ToftPanel的onButtonClick(bo)方法进行事件响应)。节点打开时,真正运行的是FramePanel实例,它提供了ButtonBar进行按钮展示,TitlePanel进行节点标题的显示,同时将用户开发的ToftPanel子类放置到中心位置进行展现。下图是ToftPanel区域介绍
NC-UAP 总体介绍
NC-UAP作为基于多组织架构的企业应用运行平台、基于模式化的开发平台、开放的系统集成平台及统一的系统管理平台,是建立在Java语言所提供的强大功能的基础上开发的。Java是一种简单的、面向对象的、分布式的、结构中立的、安全的、可移植的、性能优异的、多线程的、动态的开发语言,适合构建基于网络计算的企业应用。由于Java的平台无关性,使得NC-UAP可以运行在不同硬件平台、不同操作系统平台上。基于NC-UAP所开发的应用软件采用Browser/Server(浏览器/服务器)的方式来运行。B/S的运行方式最大限度地方便了用户部署和维护大型软件系统,保证了瘦客户机运行,从而大大降低了用户目标系统的总体拥有成本(TCO)。
系统框架层主要指基础软件,如操作系统、数据库及J2EE应用服务器。NC-UAP支持多种操作系统(Solaris、AIX、Linux、Windows等),可运行于符合J2EE规范的多种应用服务器(IBM WebSphere、BEA WebLogic、UFIDA Application Server等),支持多种数据库DBMS(DB2、Oracle、SQL Server、OSCAR等)。NC-UAP还提供Portal服务器进行内容集成以使用户对企业资源有一个统一的访问点。
技术框架层是在系统框架层(操作系统、数据库及应用服务器)和应用系统之间建立的一层技术封装层和系统资源监控和管理层。技术框架层屏蔽不同具体技术实现的细节,减少直接使用系统资源带来的复杂性、异构性、不安全性及不稳定性;技术框架层监控和管理系统资源,保证系统资源的可用性及其合理使用;技术框架层提供最佳编程模式,加快在不同技术平台上开发和部署应用的速度,保证应用的健壮性。技术框架层所屏蔽技术实现细节包括界面风格、远程接入、EJB实现/访问、多数据库适配、事务处理、并发处理、缓存处理、安全管理等等。
n 企业服务架构(Enterprise Service Architecture,ESA)
企业服务架构是一个服务集成总线,支持异构环境的服务、消息及基于事件的交互。通过ESA,可以使用与实现无关的接口来定义服务,可发现和调用所需的服务,可解决服务之间的相互依赖。
n 连接框架(Connect Framework)
连接框架连接客户端与服务器,使不同客户端(浏览器小应用程序、Java应用程序、浏览器JSP)可通过不同访问协议(HTTP/HTTPS,RMI)使用服务器提供的服务。
n 同步(Synchronization)
同步服务实现客户端与服务器代码和数据的同步,及集群环境下服务器之间的资源同步。
n SQL翻译器(SQL Translator)
SQL翻译器将SQL翻译成适合目标数据库的SQL语句,以适配不同数据库厂商提供的产品;优化SQL,充分发挥不同数据库的最大性能。
n 元数据管理(Metadata Management)
元数据是描述系统数据(包括界面定义、规则定义、流程定义等)的数据。通过元数据管理,对系统数据统一进行维护以支持用户自定义,如改变字段的可编辑属性、字段的取值范围等。
n 工作流引擎(Workflow)
工作流引擎根据工作过程的描述,通过执行一系列已定义的工作项,完成此工作过程。NC-UAP的工作流引擎支持多种工作流模式,如分支、合并、并行、选择、循环、回退等;支持工作项的抢占与会签;支持可配置的动作执行脚本,等等。
n 规则引擎(Rule Engine)
规则引擎用来定义和执行各种规则,包括界面规则、关联关系、计算规则、条件跳转规则等。使用规则可以让应用更加富有柔性。规则需要通用的行业化语言精确表达且浅显易懂。规则引擎需要满足一定的计算速度,支持规则的批量处理及理解外部数据。
n 持久化框架(Persistence Framework)
封装不同持久化技术(如JDBC、普通文件、XML、Excel)。持久化框架可解决对象与关系之间的“阻抗失配”问题。
n 基础算法(Basic Algorithms)
提供统一的基本算法,如排序,XML文档操作,方便开发与编程,统一代码规范。
n 登录和安全(Login/CA Security)
统一管理系统登录时的身份认证。支持多种身份认证策略,如静态密码认证、基于USB Key的CA身份认证等。支持对业务敏感数据使用证书进行签名和验证以防止数据篡改和提供抗抵赖性。
n 调度引擎(Scheduler)
Ø 调度引擎对服务和线程进行统一管理,以屏蔽不同应用服务器的异构性。调度引擎调度各种服务、常驻系统服务、客户端的请求服务、以及一些服务的组合。
n 异常(Exception)
统一解释与封装异常消息,如不同厂商的数据库异常的不一致。
n 缓存(Cache)
提供在服务器端与客户端的临时内存中进行缓存的机制,包括对象的创建、共享访问、假脱机(Spooling)、失效等,加快对用户操作的响应。
n 日志(Log)
日志机制提供对系统运行时的监控及支持对系统异常的追踪与定位。日志机制可控制日志输出的格式、日志信息的级别、日志信息输出的目的地(文件、控制台、SocketServer等)。通过配置文件进行灵活的设置,用户可以细致地控制日志的生成过程,而不需修改程序代码。
应用框架层是基于企业建模理论的、以业务导向和驱动的、可快速构建应用软件的软件平台。应用框架层的出现是一种技术创新,它使软件平台多了一个具有革命性意义的战略层次,为降低大型复杂软件系统的实现难度提供了新的途径。将应用软件的业务逻辑和开发技术相对分开,使得应用软件的开发者可以仅关注应用的业务逻辑,而不必关注其繁琐的技术实现。这使管理层与业务人员参与应用软件的开发成为可能。NC-UAP应用框架层基于业务和管理层面,以业务建模(组织、流程、功能、资源、信息)为基本手段,从而构造、开发和维护业务应用系统。使用NC-UAP提供的应用框架层,可大大缩短研发周期,提高研发效率,加快应用开发的速度;减少企业信息系统开发的风险;降低开发成本;实现最终用户的个性化的需求;支持用户在发展过程中各种各样的需求变化;提供应用的高价值。
n 国际化(I18N)
实现界面的多语化及数据和展示的本地化。界面的多语化是指根据用户登录时指定的语种显示相应的语言界面。企业用户可以修改相应的语言信息及显示的图片。数据和展示的本地化指日期、时间、数字、货币、汇率等可根据企业用户本地的习惯进行展示。
n 消息管理(Message Management)
消息管理集中显示通过ESA所传送的消息,如应用系统所产生的预警消息,通知消息,业务流程相关的消息,及企业公告和用户对发消息等。
n 移动管理(Mobile Management)
支持通过移动设备进行消息的交互及操纵业务数据等。对无线设备的广泛支持,NC-UAP带来的是企业管理的无处不在和服务的无限拓展,同时也为企业决策人员提供了高端、迅捷的管理机制。
n 组织管理(Organization Management)
提供从不同维度管理企业,如公司、部门、主体账簿等。
n 数据传输(Data Transfer)
数据传输负责传输以规则定义的数据集以支持数据层的应用集成。
n 数据交换(Data Exchange)
与第三方系统进行数据交换,提供灵活的数据映射及数据绑定,支持根据业务规则的转换,同时结合工作流平台整合业务流程。
n 动态会计平台(Financial Account Platform)
通过定义会计科目类别和凭证模板,使用凭证生成器,根据业务数据生成实时凭证。在保持业务数据与财务数据相对独立的基础上保证数据的一致性和及时性。
n 预警平台(PreAlert)
在预警平台上可定义多种方式的预警条件以进行形式多样的预警,如时间条件、库存大小、生日等。预警还可配置在用户登录时触发。预警消息可以用HTML网页的形式发布,可以通过邮件发布,还可使用短消息发送。
n 业务流程和审批流程的编排(Business Process and Approval Flow Orchestration)
用来定义业务流程和审批流中数据的流向,数据间的关系及以人员的关系。
n 访问控制(Access Control)
使用基于用户角色和对象权限的权限分配方式。每一角色都包含公有权限和属于某一具体公司的私有权限。角色还提供信任功能。
n 应用模式(Application Patterns)
NC-UAP根据经验积累与用户实施,总结出一套与应用界面相关的模式(表单、报表和打印),更好地提供满足用户需求的界面展现,更快地满足用户个性化的需求。
NC的开发模型
系统前端为客户端UI代码,UI端代码继承ToftPanel,UI代码通过调用远程组件与服务器端进行交互,中间传递的数据模型为VO,远程组件调用底层的业务实现代码,完成整个交互逻辑。通过JDBCFramework,系统提供了一套良好的数据持续机制,解决数据库交互的复杂问题。
下图是NCV5的代码结构图
NC5后将代码分区域存放:
Public目录存放 接口和公共代码(比如VO和公共算法)
Private目录存放 实现和其它实现细节
Client目录存放 客户端代码
META-INF目录存放模块配置文件目录,包括module.xml文件和xxx.upm接口配置文件。
针对上面的开发模式,我们规范一下代码的包结构:
nc.itf.<模块>: 表示该模块定义的接口
nc.impl.<模块>:表示该模块定义的接口实现
nc.vo<模块>: 表示VO的实现
nc.bs.<模块>: 普通的后台应用
nc.ui.<模块>.*: 客户端代码
实例讲解
V5.X版本的远程组件开发是基于接口,因此远程组件的开发按照下面三个步骤开发:
- 定义远程接口,注意这里的远程接口不用实现java.rmi.Remote接口,普通接口就可以了;
- 对该接口进行实现;
- 把该组件部署为远程组件;
下面以HelloWord为例(该实例在培训教程提供的“\配套示例\示例代码”目录下nc5Xsample.rar文件中)讲解远程接口的开发。
定义接口
package nc.itf.sample; public interface IHelloWorld { String sayHello(String toName); }
实现该接口
package nc.impl.sample; import nc.itf.sample.IHelloWorld; public class HelloWorldImpl implements IHelloWorld { public String sayHello(String toName) { String retValue = "Welcome " + toName + " explore V5"; System.out.println(retValue); return retValue; } }
部署组件
编辑或新建该产品模块下的模块部署描述文件(META-INF下的ncdemo.upm文件),加入一个公共组件:
远程组件只要指出他的remote属性为true即可。
<?xml version="1.0" encoding="gb2312"?> <module name="nc.itf.ncdemo.ejb.NCDEMOSpublicEJB"> <public> <component priority="0" remote="true" singleton="true" supportAlias="false" tx="CMT"> <interface>nc.itf.sample.IHelloWorld</interface> <implementation>nc.impl.sample.HelloWorldImpl</implementation> </component> </public> </module>
组件配置说明
- 配置文件规范
- 组件分为公共组件和私有组件,分别在public段和private段,如下所示。
<?xml version="1.0" encoding="gb2312"?>
<module name="testEJB">
<public>
<component priority="0" singleton="true" remote="true" tx="NONE" >
<interface>nc.itf.sample.IHelloPub</interface>
<implementation>nc.impl.sample.HelloWorldPub</implementation>
</component>
</public>
<private>
<component name="IHelloWorld" priority="0" singleton="false" >
<implementation>nc.impl.sample.HelloWorldImpl</implementation>
</component>
</private>
</module>
公共组件的主要配置属性
name:组件的名称,如果没配,默认为第一个接口的名称,如果没有接口,为实现类的名称
singleton: 是否为单例,默认为true
remote: 是否能够被远程调用到,默认为false,远程组件必须要有接口
tx: 事务属性, NONE表示没有事务,CMT表示容器管理的事务,BMT表示Bean管理的事务
cluster: 标志组件的集群属性,默认为NORMAL,表示不是集群组件,SP表示为单点组件(必须有接口)
supportAlias: 默认为false,表示是否能够按照接口进行查找组件
私有组件的配置属性
除了没有remote,tx属性,其余属性都支持
supportAlias建议为false
3.2.5.客户端调用
(该实例在培训教程提供的配套示例代码的工程NC_DEMO里的client端TestHelloWorldRemotInterface.class中已经实现)
接下来客户端就可以通过下面的方式进行远程访问了:
package nc.ui.sample; import nc.bs.framework.common.NCLocator; import nc.bs.framework.test.AbstractTestCase; import nc.itf.sample.IHelloWorld; public class TestHelloWorldRemotInterface extends AbstractTestCase { public void test123() { try { //远程接口调用 IHelloWorld hello = (IHelloWorld) NCLocator.getInstance().lookup( "nc.itf.sample.IHelloWorld"); System.out.println(hello.sayHello("uap")); } catch (java.lang.Throwable ivjExc) { ivjExc.printStackTrace(); } } public TestHelloWorldRemotInterface() { super(); } }
系统输出:
Welcome uap explore V5
注意:
1、此处客户端调试代码通过junit来实现。通过junit运行调试接口比较方便,不需要进行客户端登陆。具体做法如上面代码,新做一个类继承AbstractTestCase,实现一个以test开头的方法,在方法里面写调用远程组件的方法。然后以JUnit来运行就可以了;
2、在JUnit运行的调试时,在Preferences的MDE Development页签中的模块选择中建议只选UAP相关模块,其他模块不要选择,否则在调试时可能会出错;
你的一个实现可以同时实现多个接口,并且可以在部署的时候选择性的公布出你需要远程分布的接口,例如你的一个实现类,实现了多个接口IService1, IService2, IService3,你可以选择只远程公布接口IService2, IService3,部署信息如下:
<?xml version="1.0" encoding="UTF-8"?> <module name=" nc.itf.ncdemo.ejb.NCDEMOSpublicEJB"> <public> <component priority="0" remote="true" singleton="true" supportAlias="true" tx="CMT"> <interface>nc.itf.sample.service.IService2</interface> <interface>nc.itf.sample.service.IService3</interface> <implementation>nc.impl.sample.service.MultiServiceImpl</implementation> </component> </public> </module>
注意:
我们使用了supportAlias属性,指出我们可以通过两个接口中的任何接口进行远程组件的查找。supportAlias为true只有在公共组件中才起作用。
客户端代码说明
客户端调试代码可以通过junit和注册Toftpanel来实现。
通过junit运行调试接口比较方便,不需要进行客户端登陆。新做一个类继承AbstractTestCase,实现一个以test开头的方法,在方法里面写调用远程组件的方法。然后以JUnit来运行。
Toftpanel方式是写一个ToftPanel的子类,将此类注册成nc节点,然后通过eclipse启动jstarter来进入nc,点击相应节点执行相应方法。通过扩展ToftPanel,实现getTitle()方法,在postInit()方法中初始化界面,调用setButtons(ButtonObject[])方法设置菜单,实现onButtonClicked(ButtonObject)方法响应菜单事件。