TDS应用开发参考手册
(个性应用组件开发参考手册)
上海棠棣信息科技有限公司
产品研发部
2011年02月
1 [内部资料,请勿外泄] 11/10/2015
TDS 个性应用组件开发参考手册
文档信息及修订记录
项目名称 项目编号 项目经理 文档主送 文档抄送 修 订 人 胡安强 吴芳祥 TDS平台 修订日期 2011-2-25 2012-5-28 修订说明 初稿 修改,整理
版本号 1.0.0 1.0.1 文档密级 项目总监 内部
2 [内部资料,请勿外泄] 11/10/2015
TDS 个性应用组件开发参考手册
目录
1.1 个性应用组件开发说明 ..................................................................................................... 4 1.2 原子函数开发 ..................................................................................................................... 4
1.2.1 原子函数接口规范 ................................................................................................... 4 1.2.2 原子函数开发过程 ................................................................................................... 5 1.2.3 ETF数据操作 ........................................................................................................... 9 1.2.4 应用私有配置文件使用说明 ................................................................................... 9 1.2.5 日志调试与跟踪 ..................................................................................................... 10 1.3 表达式开发 ....................................................................................................................... 10
1.3.1 表达式开发规范 ..................................................................................................... 10 1.3.2 表达式开发实例 ..................................................................................................... 10 1.4 Interceptor开发 ................................................................................................................ 11
1.4.1 Interceptor开发规范 .............................................................................................. 11 1.4.2 应用实例 ................................................................................................................. 12
3 [内部资料,请勿外泄] 11/10/2015
TDS 个性应用组件开发参考手册
1.1 个性应用组件开发说明
个性应用组件扩展主要用在平台提供的公共组件无法满足应用需求的时候,可以自己编写java代码完成相关功能。
本文档主要介绍常用的个性扩展方式及个性扩展所必须遵循的相关接口。
一般而言,个性应用扩展的.jar/.class文件均放置于应用的classpath下($TDSHOME/app/$APPNAME/lib或者$TDSHOME/app/$APPNAME/classes目录).此外原子函数与表达式需要在app.xml的atc或者expr标签中声明(atc标签用于声明原子函数,expr标签用于声明表达式),声明格式如下:
如果个性扩展中需要编写tdplugin.xml文件的话,需要注意的是tdplugin.xml文件中的name属性必须全平台唯一,否则平台启动会报错. 另外,为了防止应用个性扩展的java类名与TDS平台的类名产生命名上的冲突,最好在个性扩展类的命名的过程中添加当前应用所属的项目名或应用名为包名元素之一.
1.2 原子函数开发
原子函数是TDS平台封装的一个可执行的功能组件.通常用来完成一段业务逻辑处理或者特殊功能实现.
1.2.1 原子函数接口规范
原 型 举 例
接口原型
@Named(\"TdFtpPut\")
public static int TdFtpPut(@Named(\"url\") String url,
@Named(\"port\") int port, @Named(\"username\") String username, @Named(\"password\") String password,
@Named(\"pathname\") String pathname, @Named(\"filename\") String filename)
组 件 以上为组件接口规范实例,@Named为函数名和参数名的标识,将接口中需
4 [内部资料,请勿外泄] 11/10/2015
TDS 个性应用组件开发参考手册
格式说明 组件调用说明
要被配置文件调用的参数用@Named标识,不需要的就不用标识。 在配置文件中,组件的调用通过 do 节点的属性function值为被@Named标识了的函数名,para节点后的name属性为对应组件中被@Named标识了的参数名,value值为参数名对应的值。 注意事项 组件开发好后需要打成jar包方可被调用。组件只是提供了一个接口,真正功能的实现不一定要在组件接口中实现。 补充说明 组件静态公共函数除@Named还有@Optional 1.2.2 原子函数开发过程 No.1 说 明 新建java类。 该java类与普通的java类相同。 No.2 说 明 注意事项 编写代码,实现目标功能。 代码的编写,根据实际需要进行,需要什么功能,就实现什么功能。 目标功能实现后要进行单元测试,以保证开发的功能与需求一致、无误。 No.3 说 明 标注组件接口。 将通过测试的方法,按照上面的组件接口规范,编写规范的组件接口方法,调用目标功能方法,并测试。注意@Named标识需要引入javax.inject.Named包。 No.4 说 明 调用组件 将组件所在类的src目录打成jar包,放在平台的lib目录,并把该组件开发中因需要而引入的jar一并放置在lib目录下。然后在交易中调用该组件进行测试。 组件开发实例: 例如要开发一个具备ftp文件上传下载工具的组件。 5 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 import ……; public class FtpPut { public boolean uploadFile(String url, int port, String username, } String password, String pathname, String filename, InputStream input) { FTPClient ftp = new FTPClient(); int reply; try { if(port != 0){ ftp.connect(url,port);// 连接服务器; }else{ } ftp.login(username, password);// 登录服务器 reply = ftp.getReplyCode();// 返回状态码 if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect();// 断开连接 return false;// 上传失败 } ftp.changeWorkingDirectory(pathname); ftp.storeFile(filename, input); ftp.logout();// 登录 ftp.connect(url); input.close();// 关闭流 } catch (IOException e) { } return true; e.printStackTrace(); try { } if (ftp.isConnected()) { } try { ftp.disconnect();// 断开连接 } catch (IOException e) { } input.close(); } catch (IOException e1) { } finally { //文件下载 public boolean downFile(String url, int port, String username, String password, String remotePath, String fileName, String localPath) { 6 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 } FTPClient ftp = new FTPClient(); int reply; try { if (port != 0) { ftp.connect(url, port);// 连接 } else { ftp.connect(url);// 默认端口 } ftp.login(username, password);// 登录 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect();// 断开 return false;// 上传失败 } ftp.changeWorkingDirectory(remotePath);// FTP服务器目录 FTPFile[] fs = ftp.listFiles(); for (FTPFile ftpFile : fs) { } if (ftpFile.getName().equals(fileName)) { File localFile = new File(localPath + \"/\" + ftpFile.getName()); OutputStream outs = new FileOutputStream(localFile); ftp.retrieveFile(ftpFile.getName(), outs); outs.close();// 关闭流 } ftp.logout();// 登录 } catch (IOException e) { } return true; e.printStackTrace(); if (ftp.isConnected()) { } try { ftp.disconnect();// 断开 } catch (IOException e) { } } finally { //文件上传 public void uploadFromLocal(String url, int port, String username, String password, String pathname, String filename) { FileInputStream ins = new FileInputStream(new try { File(\"F:/test.txt\")); 7 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 } boolean blag = uploadFile(url, port, username, password, filename, ins); pathname, System.out.println((blag == true) ? \"文件上传成功\" : \"文件上传失败\"); } catch (FileNotFoundException e) { } e.printStackTrace(); public void downFileFromF(String url, int port, String username, String password, String remotePath, String fileName, String localPath) { fileName, localPath); boolean blag = downFile(url, port, username, password, remotePath, System.out.println(blag == true ? \"文件下载成功\" : \"文件下载失败\"); } // 组件 上传 @Named(\"TdFtpPut\") public static int TdFtpPut(@Named(\"url\") String url, @Named(\"port\") } // 组件 下载 @Named(\"TdFtpGet\") public static int TdFtpGet(@Named(\"url\") String url, @Named(\"port\") @Named(\"password\") String password, @Named(\"pathname\") String int port, @Named(\"username\") String username, pathname, @Named(\"filename\") String filename) { new FtpPut().uploadFromLocal(url, port, username, password, return 0; pathname, filename); int port, @Named(\"username\") String username, @Named(\"password\") String password, } } @Named(\"remotePath\") String remotePath, @Named(\"fileName\") String fileName, @Named(\"localPaths\") String localPath) { new FtpPut().downFileFromF(url, port, username, password, return 0; remotePath, fileName, localPath); 若在主控中调用该组件,OXXXXXXX_CTL.XML文件实例: 8 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 1.2.3 ETF数据操作 在个性组件中,最常用的ETF数据操作函数包括以下三个: getChildValue:从一颗ETF树中取一个子节点的数值 setChildValue:添加或修改ETF树一个子节点的数值。 deletcChild:删除ETF树的一个数据子节点。 1.2.4 应用私有配置文件使用说明 目前只支持XML格式应用私有配置文件。 应用私有配置文件将在服务初始化时加载到内存中,并在交易初始化时加载到交易私有 空间。 每一个私有配置文件都有一个文件名标识,应用通过此标识访问私有空间中的配置文 件,文件名标识的命名按照业务平台规范以以本业务缩写为前缀,并且在所有需加载到数据源的数据项的命名中唯一。 9 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 取私有配置文件根节点可调用业务平台接口函数来处理 1.2.5 日志调试与跟踪 ETF报文中添加日志调试与跟踪信息 引入ILog静态API import tangdi log .ILog; private ILog logger; 错误日志记录函数 函数:logger.error(Throwable arg0,String arg1,Object... arg2); 功能:格式化输出错误日志信息,一般在捕获异常时打印该日志信息。在sys.log文件中查看该错误日志记录。 调试日志记录函数 函数:logger.info(String arg0, Object ... arg1); 功能:格式化输出调试日志信息,日志文件为TRCDIR/XXXXXXX.trc。XXXXXXXX为交易编号,在接入后由平台唯一分配。 应用配置过程 1.3 表达式开发 表达式通常用在ITF/OTA中,是一种不通过原子函数的一种功能组件. 1.3.1 表达式开发规范 TDS平台中,表达式的开发需要注意以下三点: 1. 一个表达式为一个静态函数; 2. 静态函数名与表达式名一致且全部大写; 3. 表达式函数能够自动类型转换。 1.3.2 表达式开发实例 以下为SUBSTR表达式的开发范例: public static String SUBSTR(String args, int pos, int len) 10 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 { } int beginIndex = pos - 1; if (beginIndex < 0) beginIndex = 0; beginIndex = args.length(); if (beginIndex > args.length()) int length = len; if (length < 0) length = 0; length = args.length() - beginIndex; if (beginIndex + length > args.length()) byte bytes[] = args.getBytes(); return new String(bytes, beginIndex, length); 表达式语法 1.4 Interceptor开发 Interceptor主要用在渠道接入接出的位置,用于处理对渠道接入拉出的报文或其它相关数据在渠道层统一处理. 1.4.1 Interceptor开发规范 原 型 接口原型 public class InterceptorName implements Interceptor { } public Object call() throws Exception { } public void setTarget(Callable arg0) { } //code here //code here 接口说明 使用说明 Interceptor必须实现tangdi.interceptor.Interceptor这个接口。 Interceptor可以用在listener或者connector中. 拦截器可以配置相关参数,具体遵循java bean的setter规范. 备 注 11 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 1.4.2 应用实例 下例中的拦截器为接收当前消息报文,并将其存储于交易数据区中,可以从外部配置数据区名字,默认为名为tmp的交易临时区中. 1.4.2.1 Interceptor代码如下 package tangdi.comm.xml; import java.util.concurrent.Callable; import tangdi.engine.context.BS; import tangdi.engine.context.Msg; import tangdi.interceptor.Interceptor; public class TdStoreRevMsgInterceptor implements Interceptor { } private Callable target = null; private String tmpNam = \"#tmp\"; public Object call() throws Exception { } public void setTarget(Callable arg0) { } public void setTmpNam(String tmpNam) { } this.tmpNam = tmpNam; target = arg0; byte[] data = BS.readAll(); Msg.set(tmpNam, data); return target.call(); 1.4.2.2 应用配置文件 12 [内部资料,请勿外泄] 11/10/2015 TDS 个性应用组件开发参考手册 13 [内部资料,请勿外泄] 11/10/2015 因篇幅问题不能全部显示,请点此查看更多更全内容