NCV5-基础框架技术红皮书.doc_第1页
NCV5-基础框架技术红皮书.doc_第2页
NCV5-基础框架技术红皮书.doc_第3页
NCV5-基础框架技术红皮书.doc_第4页
NCV5-基础框架技术红皮书.doc_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基础框架技术红皮书NC-UAP 5.0用友NC-UAP2020-02-091第 页目 录第一章前言1第二章构造开发环境2第三章开发模型4第四章开发远程组件51.定义接口:52.实现该接口:53.部署组件5第五章开发事务型组件71.定义接口72.实现接口:83.部署为私有组件94.发布组件接口9第六章组件实现的混合发布11第七章开发服务组件121.服务组件开发122.定义服务组件接口123.实现服务组件的接口134.部署ServiceComponent14第八章开发拦截组件151.拦截组件开发16第九章如何获取组件171.拦截组件开发18第十章组件配置信息191.配置规范20第十一章依赖注射221.只通过构造进行注射222.只通过属性进行注射233.两者都采用244.注射的值的类型245.注意点27第十二章依赖注射与ServiceLoctor模式28第十三章其他291.客户端资源加载292.框架的主目录293.Servlet开发29第十四章限制服务组件运行30第十五章Cluster开发32第十六章商业中间件扩展编程331.消息广播332.线程编程363.锁383.1普通锁处理383.2动态锁处理40第十七章开发与调试41第十八章BMT开发421.目标422.开发步骤423.注意点42第 45 页第一章 前言基础技术框架主要解决了在J2EE下的应用开发的一些复杂性问题。通过基础技术框架,提供了一套模块化的产品开发模式,屏蔽了底层技术平台的开发部署的复杂性,实现了与第三方中间件无缝集成的能力。基础技术框架的服务开发采用普通Java类(POJO、POJI)的开发模型,并为系统提供一个分布式的业务部署和运行环境。 客户端运行环境财务客户端物流资金http/https调用代码下载客户端服务接入运行环境中间件件业务组件服务器基础技术框架J2EE服务器数据库JDBCFramework(图2-1)基础技术框架概要第二章 构造开发环境通过Eclipse插件,为开发人员提供了一个基于基础技术平台进行开发的开发环境。开发人员首先下载nc.uap.mde系列插件,然后安装,安装即把插件直接考贝Eclipse的plugin目录下,由于Eclipse的bug,如果曾经安装过,请把configuration目录下的内容除了config.ini外其他文件都删除,在此启动Eclipse即可。安装成功后,首先为工作的workspace中进行基础技术平台相关的设置Window-Prefreence-MDE Development,如下图所示:NC_HOME指定基础技术平台的运行环境根目录,复选框表示是否把模块的client下的类加入到构件路径。如果你的模块不依赖别的模块的客户端代码,请取消该选择。同时尼克一机型默认数据源的配置,并进行测试。构建工程的方式有两种方式:直接创建一个MDE工程和把一个已经存在的工程转化为MDE工程。直接创建:File-New-Project-MDE Project,按照Wizard进行工作,开发一个新的工程,转化方式为在一个非MDE工程中,右击工程,在弹出菜单中点击。如果直接创建了MDE工程,工程结构如下:Wizad自动创建了public源目录,存放服务接口和依赖类(如VO),private源目录存放实现类,client源目录存放ui代码,而gen目录存放通过部署生成的文件。有了开发环境,你可以利用MDE编辑器进行组件配置,组件部署的工作,具体工作请安装后直接使用体会。MDE工程必须把自动构建选项选上Build Automatically,否则不能够进行自动的开发环境内容与基础技术平台调试运行内容保持同步。第三章 开发模型(图5-1)开发模型系统前端为UI代码,UI代码通过远程组件与服务器端进行交互,中间传递的数据模型为VO,远程组件调用底层的业务实现代码,完成整个交互逻辑。通过JDBCFramework,系统提供了一套良好的数据持续机制,解决数据库交互的复杂问题。针对上面的卡法模式,我们规范一下代码的包结构: nc.itf.: 表示该模块定义的接口 nc.impl.:表示该模块定义的接口实现 nc.vo: 表示VO的实现 nc.bs.: 普通的后台应用 nc.ui.*: 客户端代码 表示包模块的部分在包的第三个部分,如nc.bs.schedule,中的schedule,在第四章 开发远程组件V5.0版本的远程组件开发是基于接口,因此远程组件的开发按照下面两个步骤开发:1) 定义远程接口,注意这里的远程接口不用实现java.rmi.Remote接口,普通接口就可以了2) 对该接口进行实现3) 把该组件部署为远程组件下面以HelloWord为例子:1. 定义接口:package nc.itf.sample.service;public class IHelloWorld String sayHello(String toName);2. 实现该接口:package nc.impl.sample.service;public class HelloWorldImpl implements IHelloWorld public String sayHello(String toName) String retValue = Welcome + toName + explore V5;System.out.println(retValue);return retValue;3. 部署组件编辑或新建该产品模块下的模块部署描述文件(META-INF下的.module文件),加入一个公共组件: nc.itf.sample.service.IHelloWorld nc.impl.sample.service. HelloWorldImpl 远程组件只要指出他的remote属性为true即可。接下来客户端就可以通过下面的方式进行远程访问了:IHelloWorld hello = NCLocator.getInstance().lookup(nc.itf.sample.service.IHelloWorld); System.out.println(hello.sayHello(uap);系统输出:Welcome uap explore V5你的一个实现可以同时实现多个接口,并且可以在部署的时候选择性的公布出你需要远程分布的接口,例如你的一个实现类,实现了多个接口IService1, IService2, IService3,你可以选择只远程公布接口IService2, IService3,部署信息如下: nc.itf.sample.service.IService2nc.itf.sample.service.IService3 nc.impl.sample.service.MultiServiceImpl 注意我们使用了supportAlias属性,指出我们可以通过两个接口中的任何接口进行远程组件的查找。supportAlias为true只有在公共组件中才起作用。第五章 开发事务型组件事务型的组件是指该组件的方法调用中事务处理会自动参与,这类组件的开发与远程组件类一样,也是基于接口的,同样我们对接口没有任何的特别要求, 普通借口就可以了。V5.0中的事务参与模型通过方法名后缀进行判断,判断的方法如下: 方法名后缀RequiresNew: 新事物 方法名后缀Mandatory: 必须在一个已有的事务环境中运行改方法 方法名后缀Supports: 只是支持事务,不建议使用 方法名后缀NotSupported:不支持事务,不建议使用 方法名后缀Never:不能有事务,否则出错 没有方法名后缀: 如果有事务,就在该事务环境下工作,否则新启事务,这是大部分事务型组件的情况事务型组件一般都是针对数据库等事务性资源进行操作,如果没有对事务性资源进行操作,请不要把组件定义为事务性组件。事务性组件也是基于接口的,你的组件实现的类可能实现了多个接口,但是并不是所有的接口都需要公布为需要事务的,你可以选择性的公布需要事务加入的接口,而其他接口保持普通接口的逻辑。事务型组件开发过程:1) 定义接口2) 进行实现3) 把实现发布部署为私有组件4) 把多个需要部署为事务性组件的多个私有组件进行发布出去下面以单据模板中的应用作为例子:1. 定义接口package nc.itf.uap.billtemplate;import nc.vo.pub.BusinessException;import nc.vo.pub.bill.BillTempletVO;public interface IBillTemplateBase public abstract String deleteWithValidate(String id)throws BusinessException;public abstract void overWriteBillTempletVO(BillTempletVO btVO)throws BusinessException;public abstract String insertEx(BillTempletVO btVO)throws BusinessException;public abstract String copySysTemplate(String billid)throws BusinessException;2. 实现接口:package nc.impl.uap.bill;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.Comparator;import nc.bp.itf.template.ITemplateBP;import mon.NCLocator;.public class BillTemplateImpl implements IBillTemplateBase, IBillTemplateQry private ITemplateBP tempBp = null;public String deleteWithValidate(String id) throws BusinessException.public void overWriteBillTempletVO(BillTempletVO btVO) throws BusinessException .public String insertEx(BillTempletVO btVO) throws BusinessException.public String copySysTemplate(String billid) throws BusinessException. /IBillTemplateQrys methodpublic BillTempletVO findCardTempletData(String id) throws BusinessException .public ITemplateBP getTempBp() return tempBp;public void setTempBp(ITemplateBP tempBp) this.tempBp = tempBp;注意塔实现了多个接口,但是IBillTemplateQry接口我们并不把它公布出来为事务型的组件接口。3. 部署为私有组件 nc.impl.uap.bill.BillTemplateImpl 4. 发布组件接口通过开发环境提供的插件你可以把该组件进行发布,发布后配置组件在对应的配置文件的proxy.module文件中,内容如下: nc.itf.uap.billtemplate.IBillTemplateBase nc.itf.uap.pf.IPFTemplate nc.impl.uap.template.TemplateEJB IBillTemplateBase 这里我们制定了tx属性来表示发布为一个事务型发布,事务型发布tx属性必须为CMT。从该配置我们还可以看出,该接口同时发布为远程的(remote属性为true),一个组件可能同时为远程组件和事务型组件。复杂的远程组件的部署方式也可以采用这种方式(我们称为私有/发布模式,发布后的组件必须在公共区域)进行,这样可以减少远程代理的树木,提供远程组件的查找效率。第六章 组件实现的混合发布一个组件的实现可以实现多个接口,这多个接口中,有些只发布为远程组件(第4节中的例子),有些组件只发布为事务型组件(只要remote属性为false即可),也有可能同时发布为远程的和事务的(第5节中的例子),还是以前面单据模板的组件作为例子,我们只把IBillTemplateQry只发布为远程性组件,而IBillTemplateBase,发布为远程而且事务型组件(前面已发布),只要加入下面的组件配置即可: nc.itf.uap.billtemplate.IBillTemplateQry nc.impl.uap.bill.BillTemplateImpl 该实现的接口IBillTemplateQry只发布为远程组件,而IBillTemplateBase同时为远程组件和事务组件。第七章 开发服务组件在系统应用中经常需要集成一些特殊的服务,他们需要在系统启动时进行启动,如调度引擎的服务,这类服务通过实现ServiceComponent进行。服务组件的类结构如下:(图9-1)服务组件的开发模型服务器启动时,回调服务组件的start方法,停止时回调,isStared获取服务的活动状态。1. 服务组件开发开发服务组件的过程如下:1. 定义服务组件的业务接口(可选)2. 服务组件的实现必须实现ServiceComponent3. 部署到模块的module.xml中(IOC)目前规定服务组件放在nc.bs包中,如果外部不需要访问服务组件,一般发部位私有的组件,如调度引擎服务。2. 定义服务组件接口该部分的工作为可选的。package erfaces;public interface IServerStatusAware public long getTime();3. 实现服务组件的接口package nc.bs.bank.client;import f.IServerStatusAware;import ponent.ServiceComponent;public class ServiceStatusAware implements IServerStatusAware, ServiceComponent boolean bStarted; public long getTime() return System.currentTimeMillis(); public void start() throws Exception bStarted = true; System.out.println(Start at: + getTime(); public void stop() throws Exception bStarted = false; System.out.println(Stop at: + getTime() ); public boolean isStarted() return bStarted; 系统在启动时会调用start,而系统停止时会调用stop4. 部署ServiceComponent与普通的组件部署方式相同: erfaces.IAccountBS nc.bs.bank.impl.AccountBS f.IBalanceBP erfaces.IBalanceBP nc.bp.bank.impl.BalanceBP nc.bs.bank.impl.ServiceStatusAware 由于我们并不关心该服务的接口,因此只要配置实现既可,这时候组件的名称默认为实现的名称,这里我们把她配置为private的组件,可以根据需要配置为合适的模型。第八章 开发拦截组件拦截组件主要用于对组件提供拦截的功能,目前的实现采用继承的方式进行实现,特别适用于需要自己进行实现的需要通过中间件抽象框架进行调度的组件。拦截组件在系统中的接口为ponent.InterceptableComponent(11-1)拦截组件模型preInvoke在每个接口方法执行前执行,postInvoke在每个接口方法执行后执行。例如下面地一个例子:public abstract class ProfileableComponent extends implements InterceptableComponent long startTime; public void preInvoke(Method method, Object objs) if (Logger.isInfoEnabled() L(enter: + getClass().getName() + method.getDeclaringClass().getName(); startTime = System.currentTimeMillis(); public Object postInvoke(Method method, Object result) if (Logger.isInfoEnabled() L(levave: + getClass().getName() + method.getDeclaringClass().getName() + : + (System.currentTimeMillis() - startTime); return result; public Throwable afterThrowing(Method method, Throwable throwable) if (throwable instanceof RuntimeException | throwable instanceof Error) Logger.error(Encount error and leave: + getClass().getName() + method.getDeclaringClass().getName() + : + (System.currentTimeMillis() - startTime), throwable); return throwable; 1. 拦截组件开发拦截组件的开发必须按照接口编程的模式进行,他的开发步骤如下:1. 定义组件业务接口2. 实现业务组件,实现中必须实现InterceptableComponent3. 部署该组件由于开发拦截组件与普通组件的过程没有差异,因此这里就不举例了。第九章 如何获取组件拦截组件主要用于对组件提供拦截的功能,目前的实现采用继承的方式进行实现,特别适用于需要自己进行实现的需要通过中间件抽象框架进行调度的组件。拦截组件在系统中的接口为ponent.InterceptableComponent(11-1)拦截组件模型preInvoke在每个接口方法执行前执行,postInvoke在每个接口方法执行后执行。例如下面地一个例子:public abstract class ProfileableComponent extends implements InterceptableComponent long startTime; public void preInvoke(Method method, Object objs) if (Logger.isInfoEnabled() L(enter: + getClass().getName() + method.getDeclaringClass().getName(); startTime = System.currentTimeMillis(); public Object postInvoke(Method method, Object result) if (Logger.isInfoEnabled() L(levave: + getClass().getName() + method.getDeclaringClass().getName() + : + (System.currentTimeMillis() - startTime); return result; public Throwable afterThrowing(Method method, Throwable throwable) if (throwable instanceof RuntimeException | throwable instanceof Error) Logger.error(Encount error and leave: + getClass().getName() + method.getDeclaringClass().getName() + : + (System.currentTimeMillis() - startTime), throwable); return throwable; 1. 拦截组件开发拦截组件的开发必须按照接口编程的模式进行,他的开发步骤如下:4. 定义组件业务接口5. 实现业务组件,实现中必须实现InterceptableComponent6. 部署该组件由于开发拦截组件与普通组件的过程没有差异,因此这里就不举例了。第十章 组件配置信息模块组件的配置主要分为public和private两大块,public为公共的组件,而private为模块私有的组件。公共的组件能够被NCLocator查找,而私有的组件只能被该模块内的组件通过ComponentContext查找。每个Component配置主要有如下的属性和元素:名称意义name属性,组件的名称,可以为空interface元素,组件的接口类,如果不是远程的或者独立发版需要可以为空implementation元素,组件的实现类,一般来说必须提供remote属性,值为ture或者false,表示该组件是否被公布为远程的组件,默认为false,只对公共组件有效singleton属性,值为true或者false,表示该组件是否为组件级别的单例,默认为trueconstruct元素,指出构造该组件的构造函数factory-method元素,construct与他只能用一个,用于构造组件factory-method/methodfactory-method的属性,用于表明构造对象的方法factory-method/provierfactory-method的方法提供者,如果用引用那么会用该引用的实例创建对象,否则用一个类的静态方法。property元素,组件的属性,按照javabean的规范进行tx属性CMT,表示事务型,其他为非事务,只有公共组件有效cluster属性,默认为空,SP标示运行于主节点,其他表示与某个服务运行在同一个节点下面用例子描述一下: javax.sql.DataSource nc.bs.framework.datasource.ProxyDataSource oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:hgy:1521:mwdb scott tiger java.sql.Connectionnc.bs.framework.datasource.ProxyDataSource nc.bs.simple.impl.StaticFactory scott 28 1. 配置规范关于NC部署文件的编制规定原则:公有全名化,私有别名化例如以下范例: nc.itf.uap.busibean.ISysInitQry nc.impl.uap.busibean.para.SysInitQryImpl nc.bs.pub.para.SysInitImpl nc.bs.pub.para.update.SysInitUpdateImpl 约定如下:1. 所有的属性中不能出现(除系统生成的proxy外)supportAlias=”true|false”2. priority属性只对活动组件有用公共组件约定:3. 公共组件的属性中不能出现: name=”,4. 公共组件可以出现以下属性:tx=”NONE”,singleton=”true” /根据不同情况进行决定,建议采用trueremote=”true|false”私有组件约定1. 私有组件的节点中不能出现:2. 不能出现以下属性:tx=”,remote=”3. 可以出现以下属性: singleton=”true” /根据不同情况进行决定,建议采用truename=名称以接口名称为准(不包含包名称)第十一章 依赖注射中间件抽象框架的依赖注射通过构造函数或者属性共同进行,首先构造函数根据配置把相关的属性进行注射,然后进行属性的设置。下面逐个地进行实例:1. 只通过构造进行注射package nc.bs.simple.impl;public class People public String getName() return name;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论