论坛首页 Java企业应用论坛

JavaBean和FieldMap 静态定义和动态构建孰优孰劣?

浏览 12490 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (8) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-30  
    其实一开始构建这个FieldMap原因是要和一个比较老的C语言写的服务器通信,那个服务器通信的协议格式是文本的,一种准XML格式,什么叫准XML格式就是一种不严格的XML。客户端是java写的,GUI基于Swing库的。麻烦之处在于通信API非常底层,基本上就是String来String去,当然对于java这边来说可以将这个String解析成XML Document,然后再解析,但是显然还是非常麻烦。协议一般双方约定,很有可能是服务器的人先给出,其实就是一份XML规格。
    有人可能最先想到的是对象直接序列化成XML,但是直接序列化出来的结果未必符合服务器那边的格式要求,除非两边都有序列化和反序列化的工具才行,但是他们没有。所以就变成要XML手动构建手动解析,这实在太麻烦了。于是设计了一个FieldMap数据结构,然后底层的通信API再封装一下,看起来可以这样:
FieldMap fm = new FieldMap("Bond").putField("id","060001").putField("name","06国债01");  
CommonRemoteMsgService.requestRemoteService("服务名",fm,new CommonMsgCallback(){
    public void onMessage(CommonMsg msg){
        if(msg.isError()){
           //错误处理
        }
        else{
          //正常处理
          msg.getFieldMap();
        }
    }
});

上面这段会发向服务器这样的东西:
<?xml version="1.0" encoding="UTF-8" ?>
<Bond>
<id>060001</id>
<name>06国债01</name>
</Bond>
当然和服务器沟通的数据没有那么单纯,光靠FieldMap就可以描述的,所以还提供FieldMapSet。这样一来比起原来
代码更干净和简洁了。
0 请登录后投票
   发表时间:2009-11-30   最后修改:2009-11-30
carlkkx 写道

有人可能最先想到的是对象直接序列化成XML,但是直接序列化出来的结果未必符合服务器那边的格式要求,除非两边都有序列化和反序列化的工具才行,但是他们没有。所以就变成要XML手动构建手动解析,这实在太麻烦了。

你这句我是不同意的,什么叫他们没有呢?他们已经能正确解析他们定的XML了。实际的情况是:他们有而你没有。你所要做的就是写一个轮子去将JavaBean序列化成服务器先定义的“伪”XML。

carlkkx 写道
    其实一开始构建这个FieldMap原因是要和一个比较老的C语言写的服务器通信,那个服务器通信的协议格式是文本的,一种准XML格式,什么叫准XML格式就是一种不严格的XML。客户端是java写的,GUI基于Swing库的。麻烦之处在于通信API非常底层,基本上就是String来String去,当然对于java这边来说可以将这个String解析成XML Document,然后再解析,但是显然还是非常麻烦。协议一般双方约定,很有可能是服务器的人先给出,其实就是一份XML规格。


这种情况下,是可以利用自定义的Annotation进行format转换的,我也自己写过一些XML转换Bean的轮子,毕竟转换为强类型更能方便你在其他模块的编程,而且在转换的时候进行检查,明显的错误数据就应该拦截在接口层,不会让你将错误的业务数据带到DAO层、业务逻辑层甚至你永远都没发现...
@XML(nullable=false, regex="\\d{0,5}") private Integer spId;//sp编号
@XML(nullable=false, regex="\\d{0,5}") private Integer businessCode;//业务代码
@XML(nullable=false, regex="\\d{0,10}") private Integer locationId;//场地机构代号
@XML(nullable=false, maxByteLength=32) private String phoneReq;//请求手机号
@XML(nullable=false, maxByteLength=32) private String phoneRece;//接收手机号
@XML(maxByteLength=32) private String phoneType;//手机型号
@XML(format="yyyyMMdd") private Date vaildTime;//数据有效期


如果说要简洁,这样我觉得更简洁,不是么?

我觉得LZ的想法还是有他的价值的,但是不应该是用在JavaBean和XML数据的转换上,因为在这上边有更好的解决方法。哪怕使用在Http Form表单上,都已经有很多MVC框架自动帮你作好了,你也可以自定义格式。但是在一些小项目里,没有大框架支撑的时候,我认为LZ的工具就能发挥他的作用:将Form、Ajax提交上来的数据进行处理。但也应该是作成一个工具类,一个对String的扩展而存在
0 请登录后投票
   发表时间:2009-11-30   最后修改:2009-11-30
引用

你这句我是不同意的,什么叫他们没有呢?他们已经能正确解析他们定的XML了。实际的情况是:他们有而你没有。你所要做的就是写一个轮子去将JavaBean序列化成服务器先定义的“伪”XML。

实际上原先应该说大家都没有,虽然他们当然能正确解析他们定的XML,但是他们很可能也是没什么自动化工具的,而是手动构建和解析的。我刚刚说他们没有是从我方的角度的,即如果是我方给出格式的话,他们可能就认为我方给的不方便他们的解析,所以从这个角度来说他们没有。当然现实是一般他们给出,所以他们是一哥。
当碰到两种不同语言(编程模型也不同)要沟通的时候,协议必然要在更低的层次上约定,这种更低层次上的协议虽然灵活,但是也麻烦。
0 请登录后投票
   发表时间:2009-11-30   最后修改:2009-11-30
接口就是要隔离你们之间的实现。你不用关心他是怎么解析这个XML的,你要做的不应该只是想办法让你的JavaBean能和这个约定的XML进行绑定么?
你现在作的FieldMap其实也是要想办法将数据绑定到对方定制的XML上而已,但是事实上我们有更灵活的轮子,有很多种框架能将JavaBean和XML数据进行相互绑定、转换的,你不妨可以找找。
0 请登录后投票
   发表时间:2009-11-30  
引用

我也自己写过一些XML转换Bean的轮子,毕竟转换为强类型更能方便你在其他模块的编程,而且在转换的时候进行检查,明显的错误数据就应该拦截在接口层,不会让你将错误的业务数据带到DAO层、业务逻辑层甚至你永远都没发现...

这个,你说的有一定道理,但是如果客户端的话,也许本更没有静态定义一个Bean的必要,也许他从服务器拿到数据只是显示到GUI,也许GUI也可以更新,也许稍微会要做一些处理,但是笨重的静态定义一个Bean,有时候他们会觉得麻烦。而FieldMap没有静态定义的要求,它完全是动态构建的。
0 请登录后投票
   发表时间:2009-11-30   最后修改:2009-11-30
vlinux 写道
接口就是要隔离你们之间的实现。你不用关心他是怎么解析这个XML的,你要做的不应该只是想办法让你的JavaBean能和这个约定的XML进行绑定么?
你现在作的FieldMap其实也是要想办法将数据绑定到对方定制的XML上而已,但是事实上我们有更灵活的轮子,有很多种框架能将JavaBean和XML数据进行相互绑定、转换的,你不妨可以找找。

也许在我方本更不存在静态定义的javaBean,假设现在突然来了个需求,说客户希望能查询XXX数据,这个时候服务端给出了请求和响应的XML格式,然后客户端开发人员对于这份数据也许压根就不会定义一个静态的JavaBean,原来的话,直接解析XML得到数据然后放到GUI,现在话可能不用解析XML了,直接拿到FieldMap数据结构然后让其显示到GUI。
0 请登录后投票
   发表时间:2009-12-01  
后面其实还可以做更多自动化,比如设计FieldMap和GUI的绑定。
类似于设计这样的类:FieldMapFormBinder,FieldMapSetListBinder,FieldMapSetTable
然后类似于写下面这样的代码:
new FieldMapSetListBinder(你的JComboBox或JList).query("服务名",查询参数(当然也可能没有));

这样一行代码就完成了一个ComboBox列表的初始化了。
FieldMapFormBinder,FieldMapSetTable要更复杂一点,但是设计好如何方便的表达一些对应关系和转换,
也是可以类似这样做的。
0 请登录后投票
   发表时间:2009-12-01  
引用

你现在作的FieldMap其实也是要想办法将数据绑定到对方定制的XML上而已,但是事实上我们有更灵活的轮子,有很多种框架能将JavaBean和XML数据进行相互绑定、转换的,你不妨可以找找。

其实并不仅仅是绑定,还有动态构建,就是一开时标题所讲的。因为某一方也许本更就没有静态定义了这样一个数据结构,比如服务方给出了一个XML,那这个XML就是定义,现在通信模块会自动将这个XML构建为FieldMap或FieldMapSet,然后客户端可以直接利用这个FieldMap数据结构,而这个FieldMap并没有预先定义的。所以情况是不仅仅是想办法将数据绑定到对方定制的XML上,而是直接从对方定制的XML上动态构建数据结构。所以客户端数据结构非常轻量,因为没有定义大量的数据类。
0 请登录后投票
   发表时间:2009-12-01  
carlkkx 写道

其实并不仅仅是绑定,还有动态构建,就是一开时标题所讲的。因为某一方也许本更就没有静态定义了这样一个数据结构,比如服务方给出了一个XML,那这个XML就是定义,现在通信模块会自动将这个XML构建为FieldMap或FieldMapSet,然后客户端可以直接利用这个FieldMap数据结构,而这个FieldMap并没有预先定义的。所以情况是不仅仅是想办法将数据绑定到对方定制的XML上,而是直接从对方定制的XML上动态构建数据结构。所以客户端数据结构非常轻量,因为没有定义大量的数据类。


恩恩.
我遇到过两种情况
1.作为外部的XML接口
作为约定的XML一般不会轻易更改,如果约定的报文需要更改,不仅要开会讨论,编写概要设计,制定开发计划,上线计划等等。接口不是我们自己内部的interface,想改变就改变的,牵扯到那么多厂商的利益。
2.作为内部的XML接口
内部的接口也不是说想动就动的,你至少得和后台c++开发人员进行沟通。

还有,以上两种情况都不能逃避一个问题:数据用到那里去?你的方法解决的只是解决你那端的数据来源问题,但是并没有解决你是怎么使用这些数据的。

并且,如果是用在多个WEB页面的展示上,我可以想象到你满地都是
fieldMap.getField("iDate").getDateStringValue("yyyy/MM/dd");

的场景,但是突然要更改为yyyy-MM-dd,你就不及其被动了么?用POJO作为Model还是非常有他的实用价值的。

以上只是企图说明,如果XML报文修改,那么在这个修改所导致的工作量中,修改作为XML映射JavaBean的工作量是非常小且可以忽略不计的,至少我的经历是这样。但是如果采用FieldMap的获取数据方式,那么我一旦修改XML报文,你的修改工作量就不止是一个地方的getDateStringValue了
0 请登录后投票
   发表时间:2009-12-01  
没有 用过FieldMap ~
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics