1 前言
本文档是描述Smooks的应用情况,以及使用Jaxb替换smooks的可行性分析及实施方案,有不足之处还望谅解和指出。
2 背景
项目系统中使用Smooks出现几次死锁问题导致系统宕机,其后针对Smooks进行性能测试,同时,与jaxb进行了对比,发现Smooks存在严重的性能瓶颈的问题。
20个用户并发操作的测试数据:
50个用户并发操作的测试数据:
最终结果:
1、smooks各项指标都低于jaxb
2、jaxb的吞吐量变化不大,但平均处理时长多了4秒,比较稳定。
注:测试过程中包含了读取报文的时间(即从文件中获取报文数据,而后通过XMLBind技术进行转换),虽然时间有所偏差,但是,不影响整体测试结果。
3 Smooks的应用情况
3.1 集中式管理结构
目前,有关smooks的技术框架的使用,集中在VOS系统的销售服务层,也就是vos-app-sale-service。
如下图所示:
如果使用其他技术比如Jaxb进行替换Smooks,可以在此层可以完成即可实现。其中,vos-app-sale-service层提供了每个javabean与xml进行提供了可输入的报文,使操作更加透明。
3.2 数据类型应用
Smooks由于它仅支持String的java引用类型对象,在我们vos当中使用与xml进行绑定的Javabean的属性都是为java.lang.String,同时,每个属性的值(String类型)都不能为null,必须要一个默认空字符"",这样转换过程中才不会报错。这个局限是因为Smooks本身问题而存在的,而VOS系统把这个作为了开发规范,采用默认字符串进行属性数据与XML绑定了。
示例代码:
在这点来说,Jaxb相对比较灵活点。
1、Jaxb支持基本数据类型
2、支持对引用类型向基本数据类型正反的转换比如java.util.Date,此功能需要配置jaxb的适配器完成的。
3、Jaxb对引用类型的对象(包括了String),如果属性是引用类型,那么如果为null情况,Jaxb是不会把该字段与XML进行绑定的,就是说在XML里面看不到该字段。
对我们来说,第三点是争议比较多的,不同场景取决于不同的用法,怎么使用需要根据实际情况来判进行决策选择。但事实上,我们VOS中对javabean与xml转换如果字段属性出现null情况,默认需要在xml打印改字段的,这个前提条件是字段类型是String。
3.3 动态支持
![](http://static.oschina.net/uploads/space/2013/0802/135029_cMAQ_1177247.jpg)
如上图示,划红线区域的是vos有关smook的config文件管理路径。
Smooks对javabean与xml互转的提供了最基本转换的同时,也支持动态的转换方式,主要体现config文件可以使用模板引擎技术freemaket。
VOS中对smooks的动态支持是采用freemaket对其config进行处理完成的。
Jaxb对于动态支持是它薄弱的环节,从它本身来说,Jaxb主要是通过注解来实现JavaBean与XML的转换。所以,对注解来说,是需要编译而后无法改变的。当然也可以使用一些第三方包通过改变class字节码来实现,但这个方案尚未得到普通应用,风险比较大。
Jaxb是静态的支持,Jaxb需要替换Smooks需要考虑这部分移植的可能性,是否可以通过其他途径来完成目的。答案是肯定的,对于交换报文来说,报文本是就是静态的,为了更好抽象我们业务模型,支持动态报文,是基于重用的目的,但是,从单一职责和业务模型来说,解耦是一个大问题,面向服务肯定需要松耦合。
4 Jaxb替换smooks的可行性分析
针对Smooks的应用情况,从集中式管理结构和数据类型应用来说,Jaxb是实现替换Smooks是没有问题的。但考虑到Smooks的动态支持,需要耗费一些时间开来进行动态支持转换。从技术角度出发,是可行的。
必要考虑到风险分析:
1、其一、涉及到销售核心模块,任何差错都可能引起一些大的问题。
2、其二、涉及面广,虽然是集中,改动面积确实很大,config文件就有122个。
3、其三、技术要求更多,要求技术人员既要熟悉smooks,也要熟悉jaxb
4、其四、销售业务开发熟悉,不容易出错。
5、其五、需要测试人员进行回归测试。
5 Jaxb替换smooks技术实施
Jaxb替换smooks具体实施过程,主要目标是降低风险,平滑化进行技术切换,可根据目前紧急程度,进行具体实施过程决策选择。
具体实施过程保障:
1、需要开发人员进行smooks与jaxb的技术培训。
2、提供jaxb相关的技术基础设施,比如转换工具类,数据类型适配器等。
3、兼容两种技术,一旦出现重大情况,需要进行回退。
具体实施建议参考:
1、以点到点就行操作,确保每一步修改都没有问题。
2、对存在比较严重问题区域优先处理。
如果人数充足支持下时间的情况下,可以进行大范围推土机方式进行处理,短时间就可以出结果,风险高。
如果人数不多支持下时间足够的情况下,可以进行循环渐进方式进行处理,优先对主要的问题区域进行实施,这样操作的目的,将风险降到最低,可进可退,效率高。
6 Jaxb技术介绍
6.1 简介
JAXB(Java API for XML Binding),是一个业界的标准,提供了一个快速便捷的方式将Java对象与XML进行转换。
在JAX-WS(Java的WebService规范之一)中,JDK1.6 自带的版本JAX-WS2.1,其底层支持就是JAXB。
JAXB 2.0 基于 JSR 175 编程注释工具定义的程序注释。
6.2 JDK环境
JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。
如果使用JDK 1.5单独下载JAXB的RI即可,JAXB不支持JDK 1.4。
Jaxb官方地址:
6.3 开发指南
6.3.1 JavaBean开发
JaveBean必须实现java.io.Serializable序列化接口,在头部地方必须注解@XmlRootElement。
6.3.2 java2xml
实现对JaveBean转换成XML的实现过程。
public static String java2xml(Object obj) {
try {
JAXBContext content = JAXBContext.newInstance(obj.getClass());
Marshaller m = content.createMarshaller();
StringWriter sw = new StringWriter();
m.marshal(obj, sw);
return sw.toString();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
6.3.3 xml2java
实现对XML转换成JaveBean的实现过程。
public static Object xml2java(String xml, Class clazz) {
try {
JAXBContext content = JAXBContext.newInstance(clazz);
Unmarshaller m = content.createUnmarshaller();
StringReader sr = new StringReader(xml);
Object t = m.unmarshal(sr);
return t;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
6.4 API说明
Jaxb相关的重要的Class和Interfce。
参考文档:
6.4.1 JAXContent
是应用的入口,用于管理XML/Java绑定信息。
6.4.2 Marshaller
将Java对象序列化为XML数据。
6.4.3 Unmarshaller
将XML数据反序列化为Java对象。
6.5 常用场景
6.5.1 数组或者List属性XML绑定
Jaxb对List或者数组是需要手动处理,不然打印出来XML格式不是我们需要的。
![](http://static.oschina.net/uploads/space/2013/0802/142420_oXKS_1177247.jpg)
新增包含List的类:
在类对象中引用包含list的类属性:
6.5.2 Map属性XML绑定
Jaxb默认对Map进行处理,可能也不是我们需要格式。
![](http://static.oschina.net/uploads/space/2013/0802/143059_JFNN_1177247.jpg)
这个是带Map属性的JavaBean,但是最终结果展现不是我们需要的。
如果学会了对象属性进行适配器处理就可以解决此类问题。
6.5.3 Date属性XML绑定(适配器)
jaxb对java.uitl.Date进行处理,转换时间不是中文格式,因为java.util.Date的toString()默认是西方格式。这种风格不适合中国风,也不好认识。
下面是Date打印:
2011-09-01T00:00:00-03:00
而我们需要的是
2011-09-01 00::00:03
这时候处理如下:
![](http://static.oschina.net/uploads/space/2013/0802/143407_Sune_1177247.jpg)
6.5.4 排除属性XML绑定
JavaBean的一些属性有时候是不需要对外进行xml绑定,这时候,我们该怎么处理呢?在该字段前面进行注解@XmlTransient,表示不行对字段进行xml转换。
6.6 优化方案
往往高并发系统对吞吐量要求比较要的,所以,很多XmlBind技术都必须针对不同情况进行相应处理。而Jaxb当中, JAXBContext是属于线程安全的,但是Marshaller, Unmarshaller以及Validato都是非线程安全的。
针对JAXBContext属于线程安全的情况下,实现单例虽然有益于性能提高,但是高并发情况下,更容易出现问题。这种情况下,可以采取对象池来解决。
来源:oschina
链接:https://my.oschina.net/u/1177247/blog/149431