- 浏览: 6440 次
- 性别:
- 来自: 深圳
最近访客 更多访客>>
文章分类
最新评论
-
aisjava:
同意作者的观点,在手机上,JavaFx确实比其它技术要占优势。 ...
关于JavaFX在手机上应用! -
TKoTK:
使用 JTA阿可以在JTA事务中操作多个数据库连接,然后统一提 ...
在一个应用中连接不同种类的数据库系统,大家推荐一下比较好的实践方式! -
alloyer:
把实现原理大概说一下就好了,贴出一堆垃圾来做什么?本来还想看看 ...
一种Java对象与XML文互转的方法! -
抛出异常的爱:
zozoh 写道SSH 在一个应用里不能连接不同的 DataS ...
在一个应用中连接不同种类的数据库系统,大家推荐一下比较好的实践方式! -
zozoh:
SSH 在一个应用里不能连接不同的 DataSource 吗? ...
在一个应用中连接不同种类的数据库系统,大家推荐一下比较好的实践方式!
目前Java对象与XML文互转已经有一些现成的解决方案,例如XStream。但是我对他的性能产生了一定的怀疑(XStream依赖一些其他的组件),当然还有一个原因是由于项目本身的原因,不希望Web层和接口层互相之间有过多的依赖(使用XStream在接口层将XML转化为对象之后需要将对象传到Web层)。项目是一个分布式系统,前端是web层,后端是一个接口系统,主要用于web系统与其他系统的接口,其中一种接口使用的纯粹的XML文来作为数据交换的,这个接口系统需要将web层传过来的请求(XML文件)传递到外部系统,外部系统将处理的结果提以XML文件返回过来。业务层面已经定了好了所有的XML的请求与响应片段,主要是找到一种合理的方法来实现XML到Java对象的互转,方便前段Web系统的开发。整个处理中只使用了JDom解析XML,未使用其他的工具包。
我的设计如下:
1.在Web层需要调用外部系统接口的数据使用一些特殊的POJO来封装,他们都实现一个统一的接口,通过对该接口的调用,可以将POJO对象的数据转化为Map+List的封装方式,然后将这个Map+List传递到接口层,注意:这里与传递自定义的对象有一定的区别,Map+List内部封装的都是String类型的数据,不会在Web层和接口层之间导致依赖;
2.在接口层通过将Map+List转化为XML文,然后通过接口传递给调用系统;
3.外部系统将处理结果以XML文件返回,然后接口系统将XML转化为Map+List的对象,然后将此类对象传递到Web层,Web层直接根据业务协议从Map中获取对应的值,实际上这个传递过程不是对称的。
以下为具体的代码,供大家参考:
Web层的代码:
Web层所有的请求对象都要实现该接口
public interface MarshalEnable
{
/**
* 把对象内容按key=节点名,value=节点值的方式组装成hashmap
* @return HashMap
*/
@SuppressWarnings("unchecked")
public Map marshal();
}
所有请求对象的基类:
public abstract class BaseReq implements MarshalEnable {
//协议头常量定义
private static final String MSG_ID = "MSG_ID";
private static final String SERVICE_CD = "SERVICE_CD";
private static final String FROM = "FROM";
private static final String TO = "TO";
private static final String TIME = "TIME";
private static final String RECORD_TOTAL = "RECORD_TOTAL";
private static final String CURRENT_PAGE = "CURRENT_PAGE";
private static final String PAGE_SIZE = "PAGE_SIZE";
//源业务系统
private static final String FROM_VALUE = "WSS";
//目标业务系统
private static final String TO_VALUE = "CRM";
//本地网ID
private String wssLatnID = null;
//分页处理使用的字段,默认设置为0
//总页数
private int recordTotal = 0;
//当前页
private int currentPage = 0;
//每页记录数数量
private int pageSize = 0;
/**
* 把属性组装成Map模型
*/
@SuppressWarnings("unchecked")
public Map marshal() {
Map<String,String> map = new HashMap<String,String>();
map.put(WBConstant.WSS_LATN_ID, wssLatnID);
map.put(MSG_ID, String.valueOf(System.currentTimeMillis()));
map.put(SERVICE_CD, getServiceID());
map.put(FROM, FROM_VALUE);
map.put(TO, TO_VALUE);
map.put(TIME, String.valueOf(System.currentTimeMillis()));
map.put(RECORD_TOTAL, String.valueOf(recordTotal));
map.put(CURRENT_PAGE, String.valueOf(currentPage));
map.put(PAGE_SIZE, String.valueOf(pageSize));
return map;
}
public abstract String getServiceID();
public int getRecordTotal() {
return recordTotal;
}
public void setRecordTotal(int recordTotal) {
this.recordTotal = recordTotal;
}
public int getCurrentPage() {
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public String getWssLatnID() {
return wssLatnID;
}
public void setWssLatnID(String wssLatnID) {
this.wssLatnID = wssLatnID;
}
}
提供一个抽象类方便具体的请求类实现:
public abstract class AbstractReq extends BaseReq implements MarshalEnable {
//参数体标示符
private static final String CONTRACT_BODY = "contractBody";
/**
* 把属性组装成Map模型
*/
@SuppressWarnings("unchecked")
public Map marshal() {
Map map = super.marshal();
Map contractBody = new HashMap();
map.put(CONTRACT_BODY, contractBody);
addValue2Map(contractBody);
return map;
}
/**
* 将req对象的值放到map中
* @param map
*/
@SuppressWarnings("unchecked")
public abstract void addValue2Map(Map map);
}
一个具体的请求对象的例子:
public class ModifyCustInfoReq extends AbstractReq {
// 修改标识类型:1-客户ID(默认) 2-客户卡ID
private String identityType = null;
// 客户ID,客户卡ID
private String identityValue = null;
// 客户名称
private String cusName = null;
// 客户类型1 客户 2 用户
private String type = null;
// 客户等级
private String custClass = null;
// 区号,例如551
private String latnId = null;
// 客户性别1男2女
private String sex = null;
// 客户地址
private String custAddress = null;
// 联系电话
private String contactNumber = null;
// 证件类型编码
private String certType = null;
// 证件号码
private String certCode = null;
// 行业类型编码
private String industryCd = null;
// 行业类型名称
private String industryName = null;
// 区号 例如0551
private String areaCode = null;
// 客户类型编码
private String custType = null;
// 联系人
private List<ContactPersonReq> contactPersons = null;
// 属性集
private List<CustomerInfoAttrReq> custModifyInfoSets = null;
// 业务ID
private static final String SERVICE_ID = "exePty00002";
/**
* 设置业务ID 本方法设置为抽象方法是强制要求进行设置 将以使用常量
*/
@Override
public String getServiceID() {
return SERVICE_ID;
}
/**
* 将req对象的值放到map中
*/
@Override
@SuppressWarnings("unchecked")
public void addValue2Map(Map map) {
HashMap exePty00002 = new HashMap();
map.put(SERVICE_ID, exePty00002);
exePty00002.put("identityType", identityType);
exePty00002.put("identityValue", identityValue);
exePty00002.put("cusName", cusName);
exePty00002.put("type", type);
exePty00002.put("custClass", custClass);
exePty00002.put("sex", sex);
exePty00002.put("latnId", latnId);
exePty00002.put("custAddress", custAddress);
exePty00002.put("certType", certType);
exePty00002.put("certCode", certCode);
exePty00002.put("industryCd", industryCd);
exePty00002.put("industryName", industryName);
exePty00002.put("areaCode", areaCode);
exePty00002.put("custType", custType);
if (contactPersons != null && contactPersons.size() > 0) {
Map cpsMap = new HashMap();
exePty00002.put("contactPersons", cpsMap);
Map[] persons = new HashMap[contactPersons.size()];
for (int i = 0; i < contactPersons.size(); i++) {
persons[i] = contactPersons.get(i).marshal();
}
cpsMap.put("contactPerson", persons);
}
if (custModifyInfoSets != null && custModifyInfoSets.size() > 0) {
Map cmiMap = new HashMap();
exePty00002.put("custModifyInfoSets", cmiMap);
Map[] infos = new HashMap[custModifyInfoSets.size()];
for (int i = 0; i < custModifyInfoSets.size(); i++) {
infos[i] = custModifyInfoSets.get(i).marshal();
}
cmiMap.put("custModifyInfoSet", infos);
}
}
public static void main(String[] args) {
ModifyCustInfoReq modify = new ModifyCustInfoReq();
String result = null;
try {
result = ReqTools.getStringOfMap(modify.marshal(), "");
} catch (Exception e) {
}
System.out.println(result);
}
public String getIdentityType() {
return identityType;
}
public void setIdentityType(String identityType) {
this.identityType = identityType;
}
public String getIdentityValue() {
return identityValue;
}
public void setIdentityValue(String identityValue) {
this.identityValue = identityValue;
}
public String getCusName() {
return cusName;
}
public void setCusName(String cusName) {
this.cusName = cusName;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCustClass() {
return custClass;
}
public void setCustClass(String custClass) {
this.custClass = custClass;
}
public String getLatnId() {
return latnId;
}
public void setLatnId(String latnId) {
this.latnId = latnId;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getCustAddress() {
return custAddress;
}
public void setCustAddress(String custAddress) {
this.custAddress = custAddress;
}
public String getCertType() {
return certType;
}
public void setCertType(String certType) {
this.certType = certType;
}
public String getCertCode() {
return certCode;
}
public void setCertCode(String certCode) {
this.certCode = certCode;
}
public String getIndustryCd() {
return industryCd;
}
public void setIndustryCd(String industryCd) {
this.industryCd = industryCd;
}
public String getIndustryName() {
return industryName;
}
public void setIndustryName(String industryName) {
this.industryName = industryName;
}
public String getAreaCode() {
return areaCode;
}
public void setAreaCode(String areaCode) {
this.areaCode = areaCode;
}
public String getCustType() {
return custType;
}
public void setCustType(String custType) {
this.custType = custType;
}
public List<ContactPersonReq> getContactPersons() {
return contactPersons;
}
public void setContactPersons(List<ContactPersonReq> contactPersons) {
this.contactPersons = contactPersons;
}
public List<CustomerInfoAttrReq> getCustModifyInfoSets() {
return custModifyInfoSets;
}
public void setCustModifyInfoSets(
List<CustomerInfoAttrReq> custModifyInfoSets) {
this.custModifyInfoSets = custModifyInfoSets;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this.contactNumber = contactNumber;
}
}
如果需要将以上的对象转化为Map只需要调用其marshal()方法即可.
在接口层使用了一个类中的2个方法分别实现Map到XML和XML到Map的转化:
/**
* 用于与CRM进行时HashMap 与 XML 互转
*
* @author yangfeng
* @version 1.0
*/
public class XMLParser {
private static final Logger logger = LoggerFactory
.getLogger(XMLParser.class);
// 系统的换行符
// static final String LINE_SEP = System.getProperty("line.separator");
private static final int XML_INIT_LENGTH = 1000;
// 请求包中的行缩进
// private static final String TAB = "\t";
// XML格式符号
private static final String XML_START_LEFT = "<";
private static final String XML_RIGHT = ">";
private static final String XML_END_LEFT = "</";
private XMLParser() {
}
/**
* 根据hashmap的模型转化为内容字符串
*
* @param map
* HashMap 输入的Map
* @param tabs
* String XML文件缩进空格
* @throws Exception
* 如果HashMap中无对应类型抛出异常
* @return String 返回的XML片段
*/
@SuppressWarnings("unchecked")
public static String getStringOfMap(Map map, String tabs) {
StringBuilder sb = new StringBuilder(XML_INIT_LENGTH);
Iterator keys = map.keySet().iterator();
while (keys.hasNext()) {
Object key = keys.next();
Object val = map.get(key);
if (val == null) {// 没有值
sb.append(tabs);
sb.append(XML_START_LEFT + key + XML_RIGHT);
// sb.append("");
sb.append(XML_END_LEFT + key + XML_RIGHT);
} else {// 有值
if (val instanceof String) { // 包含int
sb.append(tabs);
sb.append(XML_START_LEFT + key + XML_RIGHT);
sb.append(val);
sb.append(XML_END_LEFT + key + XML_RIGHT);
} else if (val instanceof HashMap) { // 如果还有子节点,则递归调用
sb.append(tabs);
sb.append(XML_START_LEFT + key + XML_RIGHT);
sb.append(WBConstant.LINE_SEP);
sb.append(getStringOfMap((HashMap) val, tabs
+ WBConstant.TAB));
sb.append(tabs);
sb.append(XML_END_LEFT + key + XML_RIGHT);
} else if (val instanceof HashMap[]) { // 如果还有并列的子节点数组,则递归调用
HashMap[] maps = (HashMap[]) val;
for (int i = 0; i < maps.length; i++) {// 每个map一个节点
sb.append(tabs);
sb.append(XML_START_LEFT + key + XML_RIGHT);
sb.append(WBConstant.LINE_SEP);
sb
.append(getStringOfMap(maps[i], tabs
+ WBConstant.TAB));
sb.append(tabs);
sb.append(XML_END_LEFT + key + XML_RIGHT);
sb.append(WBConstant.LINE_SEP);
}
} else {
// 出现异常记录日志,返回空
logger.error("Unkown Object in marshal map:" + val);
return null;
}
}
sb.append(WBConstant.LINE_SEP);
}
return sb.toString();
}
/**
*
* @param xmlStr
* @return
*/
@SuppressWarnings("unchecked")
public static Map string2Map(String xmlStr) {
if (xmlStr == null) {
return null;
}
SAXBuilder builder = new SAXBuilder(false);
Document doc = null;
try {
doc = builder.build(new ByteArrayInputStream(xmlStr.getBytes()));
} catch (Exception e) {
logger.error("xml read error!!!", e);
return null;
}
Element root = doc.getRootElement();
return (Map) marshal2Map(root, null, null);
}
/**
*
* @param xmlStr
* @return
*/
@SuppressWarnings("unchecked")
public static Map string2Map(File xmlStr) {
if (xmlStr == null) {
return null;
}
SAXBuilder builder = new SAXBuilder(false);
Document doc = null;
try {
doc = builder.build(new FileInputStream(xmlStr));
} catch (Exception e) {
logger.error("xml read error!!!", e);
return null;
}
Element root = doc.getRootElement();
return (Map) marshal2Map(root, null, null);
}
/**
* 把JDOM模型解析成map模型 本方法递归调用 为了便于进行递归调用
*
* @param ele
* Element XML文件中的一个根节点
* @param superName
* 根节点对应上一级的名称
* @param supermap
* 根节点对应上一级的map
*
* @return HashMap
*/
@SuppressWarnings("unchecked")
private static Object marshal2Map(Element ele, String superName,
Map supermap) {
Map map = new HashMap();
List children = ele.getChildren();
List slist = new ArrayList();
for (int i = 0; i < children.size(); i++) {
Element child = (Element) children.get(i);
String name = child.getName().trim();
int childSize = child.getChildren().size();
if (childSize == 0) {// 无下一级节点,
String val = child.getText().trim();
if (slist.size() > 0) {
Map temp = new HashMap();
temp.put(name, val);
slist.add(temp);
} else if (map.containsKey(name)) {
Map temp = new HashMap();
temp.put(name, val);
slist.add(map);
slist.add(temp);
} else {
map.put(name, val);
}
} else {// 还有一层子节点,从根开始是第3层了,
// 重名的子节点的情况只有复杂的节点才有
Object childMap = marshal2Map(child, name, map);
if (childMap instanceof Map) {
if (map.containsKey(name)) {
if (supermap.get(superName) instanceof List) {
List tempList = (List) supermap.get(superName);
Map temp = new HashMap();
temp.put(name, childMap);
tempList.add(temp);
} else {
List list = new ArrayList();
list.add(map);
Map temp = new HashMap();
temp.put(name, childMap);
list.add(temp);
//supermap.remove(superName);
supermap.put(superName, list);
}
} else {
map.put(name, childMap);
}
} else {
map.put(name, childMap);
}
}
}
//当多个相同节点已经转化为List放入父MAP中时候需要将其作为返回对象
if(supermap!=null){
Object obj = supermap.get(superName);
if(obj!=null && obj instanceof List){
return obj;
}
}
if (slist.size() != 0) {
return slist;
}
return map;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// String path = "file:///f:/1.xml";
File file = new File("f:/document/Wss/200904/1.xml");
Map map = string2Map(file);
System.out.println(map);
}
}
以上最为复杂的应该是方法marshal2Map,该方法使用了递归调用,返回值使用的Object,为什么呢?
主要原因是因为需要使用Map+List进行封装,递归调用的返回值可能是Map也可以能是List,所以使用
了Object作为返回值,但是最终返回给其他调用方法的是Map对象,此类处理方式是很罕见的。
希望以上的代码和说明对大家有帮助。
说明:
1.该方法对于XML文件有一个小小的要求:
如下:
<abc></abc>
<dex></dex>
<dex></dex>
<dex></dex>
<dex></dex>
<sf></sf>
上面这一部分需要做一个小的改动,必须改为:
<abc></abc>
<dexs>
<dex></dex>
<dex></dex>
<dex></dex>
<dex></dex>
</dexs>
<sf></sf>
就是这点要求。
2.还有一点就是对于返回的XML文,如果是多值的话,如说明1中所示,
但是实际只有1个值的话,将可能不会使用List进行封装,而是直接使用
简单的List进行封装。
评论
本来还想看看的,现在决定不看了.
有关XStream的性能问题,抱歉,我没有去测试过,当时没有用还有一个原因是有一个小小的bug,会将A_B这样的类转化为A__B,由于时间很紧张,所以就暂时放弃了,这个应该有朋友遇到过,希望遇到过的能给出一个方案,当然不出现A_B这样的类名,肯定是可以搞定的。
别自己动手整了个轮子出来,然后才发现啊原来人家早有了。
这java 的序列化功能,想想肯定有人做了。
这个不对,dom4j一样下层可以选择SAX的实现,不过是上层api使用上不同而已。
请实际测试过之后再说它慢,你自己写一个未必性能就好。
另外不想让XStream代管所有的对象生成,可以自己定制特定xml元素的处理,不过就是继承下XStream的类,改点代码而已,框架应该有这项功能。
ps:如果数据结构不复杂,请用json
呵呵 才看见这句 不好意思 那我只能替你郁闷了
这个simple XML项目貌似发展的挺快的。不是sun已经提供了一种java 对象和 xml互相绑定的解决方案了吗
我用过这样的,但前提是数据量在可控范围内
找个时间对比下我和XStream各有什么优劣,然后想办法参与进去
相关推荐
`Unmarshaller`对象的`unmarshal()`方法会返回一个与XML对应的Java对象。 2. **DOM解析**:解析XML文件得到DOM树,然后遍历树并创建相应的Java对象。这通常需要手动编写解析代码,比较繁琐。 3. **SAX解析**:...
JAXB提供了一种自动化的机制,将XML Schema(XSD)映射到Java类,反之亦然。这允许开发者在Java应用中存储和序列化数据为XML格式,同时保持代码的简洁性和可维护性。JAXB的核心组件包括: 1. **Unmarshaller**: ...
随着软件开发的复杂化,数据交换变得越来越频繁,而 XML 作为一种通用的数据交换格式,渐渐成为开发者们的选择之一。但是,Java 对象与 XML 之间的转换却是一个复杂的问题,需要开发者们具备一定的技术背景和实践...
XML文件自动转换为Java对象工具是一种实用的开发辅助软件,它可以帮助程序员快速地将XML数据映射到Java类,从而简化了数据处理的过程。在Java开发中,XML常被用作数据交换格式,但手动编写Java类来表示XML结构既耗时...
本示例"JAVA对象与XML相互转化DEMO"聚焦于如何在Java中实现对象与XML之间的互转,这对于理解和处理数据交换至关重要。 首先,Java中实现XML到对象的转换主要依赖于JAXB(Java Architecture for XML Binding)。JAXB...
XML(Extensible Markup Language)是一种用于标记数据的语言,广泛应用于数据交换、配置文件等领域。而Java作为一种面向对象的编程语言,常用于构建复杂的应用系统。将XML数据转换为Java对象,能够方便地在两者之间...
在Java编程中,将对象转换成XML是一种常见的数据序列化方式,这有助于数据交换和存储。当遇到包含特殊字符如 "和 "&" 的文本时,XML解析器可能会产生错误,因为这些字符在XML语法中有特定含义。为了解决这个问题,...
总之,Java List与XML之间的转换是数据交换和持久化的重要手段,而dom4j库提供了一种方便的方式来实现这种转换。通过熟练掌握这些概念和方法,开发者可以更好地在Java应用程序中处理结构化的数据。
总结来说,"xml和java对象互转"涉及使用如XStream这样的库来方便地在XML和Java对象之间进行数据转换,这对于在Java应用程序中处理和交换XML数据是至关重要的。通过理解这个过程,开发者可以更高效地管理数据,并实现...
在Java编程中,XML(可扩展标记语言)是一种用于存储和传输数据的标准化格式,而Map是Java集合框架中的一个重要接口,它提供了键值对的数据结构。将XML与Map进行互转是常见的需求,特别是在处理配置文件或者进行数据...
在IT行业中,XML(eXtensible Markup Language)和Java对象之间的互转是常见的操作,尤其是在数据交换、配置文件处理和序列化等场景。本文将详细介绍两种主要的XML与Java对象互相转换的方法:DOM(Document Object ...
XStream是一个用于Java的轻量级库,它提供了一种简单的API来将Java对象序列化为XML,以及将XML反序列化回Java对象。XStream通过反射机制自动处理对象到XML的转换,无需额外的注解或配置文件。 2. **使用步骤**: -...
- Apache的XMLBeans库提供了另一种Java对象到XML的映射方式,通过生成与XML schema对应的Java类,实现了对象和XML的直接对应。 8. Castor: - Castor是一个开放源码项目,它提供了一种灵活的Java对象到XML和...
本篇文章将深入探讨一种被誉为“史上最牛逼”的Java对象转XML算法,以及它如何解决传统方法的不足。 在Java中,有多种方式可以实现对象到XML的转换,例如使用JAXB(Java Architecture for XML Binding)、DOM、SAX...
总的来说,XStream提供了一种简洁、直观的方式来处理Java对象与XML之间的转换。它的强大之处在于可以自动处理复杂的对象结构,并且允许开发者自定义XML的表示方式。通过熟练掌握XStream,可以极大地提高Java项目中...
JAXB是Java SE的一部分,它提供了将Java对象直接转换为XML文档,以及从XML文档反序列化回Java对象的能力。首先,你需要为要转换的对象创建对应的Java类,并使用`@XmlRootElement`、`@XmlElement`等注解来指定XML...
在Java编程中,XML(eXtensible Markup Language)是一种常用的数据交换格式,它结构清晰、易于阅读,常用于存储和传输数据。当处理XML文件时,有时我们需要将其内容转换为Java对象,如List,以便于操作和处理。本篇...
3. **JAXB**:JAXB是Java标准,用于在Java对象和XML之间进行自动转换。它提供了一种直观且高效的方式来绑定XML Schema到Java类,使得XML的序列化和反序列化变得非常简单。 对于Java类对象到XML的转换,JAXB是首选的...
XML(eXtensible Markup Language)是一种用于存储和传输数据的标记语言,广泛应用于软件开发、数据交换等领域。将XML转换为对象是Java编程中常见的任务,它允许开发者更方便地处理XML数据,将XML文档结构映射到Java...
它提供了一种自动的方式,使得开发者能够方便地在XML文档和Java对象之间进行数据交换,极大地简化了XML处理。JAXB允许我们将Java类与XML Schema定义的元素和类型绑定,从而实现XML的序列化和反序列化。 在Java对象...