NO.11 XML与定制Bean互转的一次笨拙的分析与实现1.概述

来源:互联网 发布:面向切面编程什么意思 编辑:程序博客网 时间:2024/05/09 05:36

    前言
    1.网上看了很多资料,都是说JavaBean与XML的互转,但实际上感觉还是叫做DTO与XML互转好一些。毕竟JavaBean的概念比较大。
    2.本文主要讲述:以XML为基础,由其定制产生的Bean与对应XML之间的互转分析与实现;
    3.看到第2条,有人也许会问为什么不使用主流的XStream等第三方工具。为:目前的三方工具均不支持数组(实际上Java反射难以实现数组型)
      这些第三方工具应对简单情况还可以,而真正的交互报文格式相当复杂,会有类似数组类型节点的出现,而这些工具不支持数组,决定了面对复杂格式XML时,只能走上定制实现之路。
    4.为什么说是笨拙的?
      实现的时候,有了让人烦的环节(下文详述),说明实现的还不太清爽...
      并没有对所有情况进行可定制。
      鉴于以上几点,故为笨拙说:)

 

一、Why?
    今年3月份,接到开发交强险平台报文交互的任务。
    交互报文是XML格式,客户要求交互可根据报文变化进行配置(后未实现),有日志记录。
    经讨论,大家产生了将报文交互独立出一个服务层的想法。

 

二、What?
    这个服务层要做什么?
    1.提供XML与定制Bean互转的统一的、透明的技术封装
      先看一下以前是如何实现报文拼写与解析的:
      有人直接使用拼串实现拼写报文,你会看到这样的代码:XML += "<node>"+nodeValue+"</node>";
      有人使用JDOM、有人使用DOM4j......当我们发现一种方式有缺陷时(比如JDOM对10M以上XML解析有问题),代码调整量会相当大。
      封装就解决了这一问题。
    2.提供报文交互的统一的、透明的技术封装
      理由同上,之前报文的发送与接收都是使用HttpURLConnection,这东西没有提供超时断开的功能,会导致网络异常时连接耗尽。
      现使用Apache的httpclient。
    3.添加其它功能
      比如客户提出交互日志、定时发送等功能。均可以在此层实现或提供接口。

 

三、How?
    此层的技术核心便是1.如何形成XML定制Bean(规则分析) 2.XML与定制Bean互转(实现)
    1.如何形成XML定制Bean(规则分析)
   
    以一个示例XML来说明吧,顺便介绍一些XML、DOM基础知识
     <!-- XML命名规则
     XML名以下划线或字母开始;
     XML名可包含字母、数字、句点、下划线和冒号;
     XML名不能包含空格;
     XML名不能以数字开始,但可包含数字;
     XML名区分大小写。
      -->
     
     <!-- XML声明 -->
     <?xml version="1.0" encoding="GB2312" standalone="yes" ?>
    
     <!-- Root是XML根结点,唯一 -->
     <Root>
      
       <!-- String型
            特征:XML Bean中最基本元素(叶子)
            转换规则:使用Java中的String表达
        -->
       <StringType>abcd</StringType>
      
       <!-- List型
            特征:其子节点全为相同对象
            转换规则:使用Java中的List表达
        -->
       <ListType>
         <ObjectTypeB>
           <StringType1>111</StringType1>
           <StringType2>222</StringType2>
         </ObjectTypeB>
         <ObjectTypeB>
           <StringType1>111</StringType1>
           <StringType2>222</StringType2>
         </ObjectTypeB>
       </ListType>
      
       <!-- Array型
            特征:兄弟节点中即含相同对象,也含其它不相同对象
            转换规则:使用Java中的List表达,但变量名采用array$开头
        -->
       <ObjectArrayType>
         <StringType1>111</StringType1>
         <StringType2>222</StringType2>
       </ObjectArrayType>
       <ObjectArrayType>
         <StringType1>111</StringType1>
         <StringType2>222</StringType2>
       </ObjectArrayType>
       <OthElement/>
      
       <!-- StringList型
            特征:子节点中全部为同名String
            转换规则:JDK找不到一个合适的类型,故为其单独建立一个StringList类

                           属性1:String stringName

                           属性2:String[] stringValues
        -->
       <StringListType>
         <StringType>111</StringType>
         <StringType>222</StringType>
         <StringType>333</StringType>
         <StringType>444</StringType>
       </StringListType>

       
       <!-- Object型
            特征:非以上情况

            另:Attribute的表达

                  使用'$'做为分隔符并以attr开头,下面的attr1在类ObjectTypeA中会表示为String attr$attr1
        -->
       <ObjectTypeA attr1="abc">123</ObjectTypeA>
      
     </Root>
     OK,一般XML的拆分不会超出以上几种情况,有了这些拆分规则,我们可以写一个解析器,将XML按规则生成定制Bean了。

     附加规则:由于采用反射实现,为了便于调用,所有的Bean必须在一个包内(否则在调用其它Bean时需要知晓它的位置)。
     

     2.XML与Bean互转(实现)

     做好定制Bean,只需要同样按照拆分规则使用反射便不难实现XML与定制Bean之间的互转了。一些相关信息可参见以下两篇:

 

NO.21 XML与定制Bean互转的一次笨拙的分析与实现2.组成

NO.22 XML与定制Bean互转的一次笨拙的分析与实现3.开发history

原创粉丝点击