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

xiaoxiao2026-05-19  13

      目前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进行封装。

转载请注明原文地址: https://www.6miu.com/read-5049040.html

最新回复(0)