一种Java对象与XML文互转的方法

目前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进行封装。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值