本框架的是为了解决 Java 语言和 SOP 通信报文之间转换的实际问题而产生。设计的思想是高度屏蔽报文的底层实现,提供灵活配置可能。整个框架的设计思路是,编排、反编排作业实现与配置信息加载进行解耦。目前配置信息加载仅实现读取 xml 配置文件。针对编排动作抽象出编排接口,反编排动作抽象出反编排接口。对于配置文件加载抽象出元信息加载器体系结构。在实际使用中使用者对以上细节是不会接触到的。 只要对核心接口和抽象类有基本的掌握即可完成开发。

作者邮箱,woate@qq.com。群:413606667

欢迎来信提供您宝贵的建议。

为何取此名?

为什么取名 TalkingBird 呢?主要是报文转换就是从一种语言编码转换为另外一种语言编码,这让我想到了鹦鹉,她即会说人话,但却不是人,有能理解鸟的语言。于是就想到了说话的鸟。再加上在 Talking in Action 的封面的鸟,即可知道,此鸟精细,但却是机械的,也有说话的能力。因此取此名即赋予该框架精细之意。

简介 - 图1

交易接口文件和头信息文件分开存放

交易接口文件是对接口主体的描述,其中涉及头信息和交易数据信息。而头信息通常不变,为了提高复用,所以将头信息抽象出来单独存放为头信息文件。他们之间使用内联特性进行引用。

边解析边创建元信息

目前加载器实现基于边解析边创建元信息,在实际开发接口中很有用处,可以准确发现配置错误的地方。

段提供三种取值模式,分别为常量模式,默认模式,用户模式。常量模式——通常一个字段会涉及常量值的情况,那样设置为constant,则编排时就是固定值,就不需要在使用时对固定值的字段设置值。默认模式——对于有初始值的字段,可以设置为default,这样如果使用时,没有设置值,则使用配置时的默认值,如果设置了值就是用户希望的值。用户模式——在配置时,如果没有设置取值模式或者设置为user,则编排时使用用户提供的值,如果没有提供值,则会提示异常。

字段间接定义

间接定义是指交易接口文件和头信息文件中的元信息池一次定义字段信息,在使用时可以多次使用 ref 属性进行引用。

别名映射

交易接口文件和头信息文件都支持别名映射,在 class 和 wrap-class 属性可以使用别名。别名在别名映射节点中集中定义。别且提供作用域domain 属性,该属性设置的不同,作用的范围不一样。

7 字符集继承

当接口文件中的Object节点定义了字符集,而Object节点下的字段节点未定义字符集,则可继承Object的字符集。

8 对Map的支持

支持反编排为Map,编排数据来源可以是Map。默认构建的是基于HashMap的实例。

一个头文件结构

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <interfaces xmlns="http://www.woate.com/talkingbird/header"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.woate.com/talkingbird/header">
  5. <!-- 别名映射,提供对别名和类全限定名之间的映射 -->
  6. <alias-mappings>
  7. </alias-mappings>
  8. <!-- 元信息池 -->
  9. <metadatas-pool>
  10. </metadatas-pool>
  11. <!-- 元信息池,提供对字段集中的定义 -->
  12. <request>
  13. </request>
  14. <response>
  15. </response>
  16. <exception>
  17. </exception>
  18. </interfaces>

一个接口文件结构

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <interfaces xmlns="http://www.woate.com/talkingbird"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.woate.com/talkingbird">
  5. <!-- 别名映射,提供对别名和类全限定名之间的映射 -->
  6. <alias-mappings>
  7. </alias-mappings>
  8. <!-- 元信息池,提供对字段集中的定义 -->
  9. <metadatas-pool>
  10. </metadatas-pool>
  11. <!-- 交易定义 name不一定是交易码,可能是组合交易的别名-->
  12. <interface name="YYYY">
  13. <!-- 请求节点 -->
  14. <request>
  15. <!-- 系统信息头 -->
  16. <sys inline="headers/sys.xml"/>
  17. <!-- 公共信息头 -->
  18. <com inline="headers/com.xml"/>
  19. <busis>
  20. <!-- 交易数据 name是交易码 -->
  21. <busi name="XXXX">
  22. <!-- 交易数据头 -->
  23. <header inline="headers/busi.xml"/>
  24. </busi>
  25. </busis>
  26. </request>
  27. <!-- 应答节点 -->
  28. <response>
  29. <!-- 系统信息头 -->
  30. <sys inline="headers/sys.xml"/>
  31. <!-- 公共信息头 -->
  32. <com inline="headers/com.xml"/>
  33. <busis>
  34. <!-- 交易数据 name是交易码 -->
  35. <busi name="XXXX">
  36. <!-- 交易数据头 -->
  37. <header inline="headers/busi.xml"/>
  38. </busi>
  39. </busis>
  40. </response>
  41. <!--异常节点-->
  42. <exception>
  43. <!-- 系统信息头 -->
  44. <sys inline="headers/sys.xml"/>
  45. <!-- 公共信息头 -->
  46. <com inline="headers/com.xml"/>
  47. <busis>
  48. <!-- 交易数据 name是交易码 -->
  49. <busi name="XXXX">
  50. <!-- 交易数据头 -->
  51. <header inline="headers/busi.xml"/>
  52. </busi>
  53. </busis>
  54. </exception>
  55. </interface>
  56. </interfaces>

编排代码

  1. SOPFactory factory = SOPFactory.getDefaultFactory().load();
  2. SOPPacket packet = factory.getSOPPacketS("YYYY");
  3. SOPSession session = SOPSession.getSession();
  4. session.setAttribute(Dictionary.YNGYJG, "1001");
  5. session.setAttribute(Dictionary.JIO1GY, "901328");
  6. SOPBusiWrapper busiWrapper = session.createBusiData();
  7. busiWrapper.setBusidata("TASKID","XXXXXXXXXXXXXXX");
  8. busiWrapper.setBusidata("ZHJGNO", Integer.toString(i));
  9. busiWrapper.setBusidata("YYJGNO", "351801");
  10. busiWrapper.setBusidata("GUIYDH", "E01100");
  11. busiWrapper.setBusidata("CLASID", "1103");
  12. busiWrapper.setBusidata("APPLID", "E01100");
  13. busiWrapper.setBusidata("SHOJHM", "1581111111");
  14. busiWrapper.setBusidata("DXINLX", "0");
  15. busiWrapper.setBusidata("DXINBM", "15");
  16. busiWrapper.setBusidata("DXINNR", "尊敬的客户:XXXXXXX");
  17. busiWrapper.setBusidata("WAPURL", "");
  18. ByteBuffer buffer = packet.format();
  19. System.out.println(Hex.toHexString(buffer.array()));

反编排代码

  1. SOPFactory factory = SOPFactory.getDefaultFactory().load();
  2. SOPPacket packet = factory.getSOPPacketS("YYYY");
  3. byte[] array = Hex.read(new FileInputStream("test2.hex"));
  4. Hex.write(array);
  5. ByteBuffer buffer = ByteBuffer.wrap(array);
  6. buffer.rewind();
  7. packet.parse(buffer);
  8. SOPSession session = SOPSession.getSession();
  9. System.out.println(session.attributes());
  10. System.out.println(session.peekFirstBusiData().attributes());
  11. System.out.println(session.pollFirstBusiData().busidatas());