相信设计到通讯的工程,都会需要用的通讯协议http、soap...,相信也写过很多的接口soap接口、HTTP+XML接口,每次调用我们写的接口的时候传给我们的都是个XML格式的数据信息,我们需要把这些数据解析出来,然后再拼装成一个info发出去,以下写了一个通用的方法,利用JAVA的反射机制来实现:
代码如下:
Java代码
/**
* <p>
* Copyright (C), 1988-2008, Huawei Tech. Co., Ltd.
* </p>
* <p>
* FileName: Transform.java
* </p>
* <p>
* Author:tangtao Version :1.0 Date:2010-8-31
* </p>
* <p>
* Description:
* </p>
* <p>
* Version: 1.0
* </p>
* <p>
* Function List:
* </p>
*/
package com.huawei.nvs.sys.conn.http;
import java.io.ByteArrayInputStream;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import com.huawei.nvs.sys.conn.http.bean.FieldInfo;
import com.huawei.nvs.sys.conn.http.bean.HttpInfo;
import com.huawei.nvs.sys.conn.http.bean.MessageInfo;
import com.huawei.nvs.sys.conn.http.bean.SendFieldInfo;
import com.huawei.nvs.sys.conn.http.conf.HttpEnv;
import com.huawei.nvs.sys.conn.http.exception.HttpException;
import com.huawei.nvs.sys.conn.http.util.ListMap;
import com.huawei.nvs.sys.conn.http.util.XmlTools;
/**
* <p>
* Title: Transform
* </p>
* <p>
* Description: HTTP消息转换类,把指定的内部实体对象转换成xml,把xml转换成指定的内部实体对象
* </p>
* <p>
* Copyright: Copyright (c) 2010-8-31
* </p>
* <p>
* Company: www.huawei.com
* </p>
*
* @author wanghui
* @version 1.0
*/
public class Transform
{
/**
* 把实体bean转换成xml字符串
*
* @param bean 实体对象
* @throws HttpException HttpException
* @return 转换成功的xml字符串
*/
public static String beanToXml(HttpInfo bean)
throws HttpException
{
if (null == bean)
{
throw new HttpException("Parameter bean is null.");
}
StringBuffer sbf = new StringBuffer("<?xml version='1.0' encoding='UTF-8'?>");
ListMap headFieldMap = new ListMap();
ListMap bodyFieldMap = new ListMap();
Class<?> c = bean.getClass();
try
{
// 获取消息类型和实体对象类路径
Field f = c.getDeclaredField("msgType");
Field v = c.getDeclaredField("version");
// 修改checkstyle 问题by wangzheng at 20101015 begin
// f.setAccessible(true);
AccessibleObject.setAccessible(new Field[] {f}, true);
AccessibleObject.setAccessible(new Field[] {v}, true);
// 修改checkstyle 问题by wangzheng at 20101015 end
String msgType = f.get(bean).toString();
String version = (String)v.get(bean);
//因为这个是发到SMC的消息,不存在多版本,所以这里默认赋值为1.0版本
version = null == version ? "smc" : version;
String path = c.getName();
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
// 找出bean中的消息头和消息体
for (Field field : fields)
{
String fieldName = field.getName();
if (isUseField(msgType, path, fieldName, version))
{
if ("MsgType".equalsIgnoreCase(fieldName) || "Expires".equalsIgnoreCase(fieldName)
|| "callID".equalsIgnoreCase(fieldName))
{
headFieldMap.put(fieldName, field);
}
else
{
bodyFieldMap.put(fieldName, field);
}
}
}
sbf.append("<NVS_SMS_REQ>");
// 拼装消息头xml字符串
String headStr = buildHead(version, msgType, headFieldMap, bean);
// 拼装消息体xml字符串
String bodyStr = buildBody(version, msgType, bodyFieldMap, bean);
// 拼装整个xml消息字符串
sbf.append(headStr).append(bodyStr);
sbf.append("</NVS_SMS_REQ>");
}
catch (Exception e)
{
e.printStackTrace();
throw new HttpException("The xml conversion bean fail.", e);
}
return sbf.toString();
}
/**
* 把实体bean转换成xml字符串
*
* @param msgType 消息类型
* @param bean 实体对象
* @throws HttpException HttpException
* @return 转换成功的xml字符串
*/
public static String beanToXml(String msgType, Object bean)
throws HttpException
{
if (null == bean)
{
throw new HttpException("Parameter bean is null.");
}
StringBuffer sbf = new StringBuffer("");
ListMap headFieldMap = new ListMap();
ListMap bodyFieldMap = new ListMap();
Class<?> c = bean.getClass();
try
{
String path = c.getName();
String version = (String)(c.getDeclaredMethod("getVersion").invoke(bean, new Object[] {}));
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
// 找出bean中的消息头和消息体
for (Field field : fields)
{
String fieldName = field.getName();
if (isUseField(msgType, path, fieldName, version))
{
if ("MsgType".equalsIgnoreCase(fieldName) || "Expires".equalsIgnoreCase(fieldName)
|| "callID".equalsIgnoreCase(fieldName))
{
headFieldMap.put(fieldName, field);
}
else
{
bodyFieldMap.put(fieldName, field);
}
}
}
sbf.append("<Msg_Body>");
// 拼装消息头xml字符串
String headStr = buildHead(version, msgType, headFieldMap, bean);
// 拼装消息体xml字符串
String bodyStr = buildBody(version, msgType, bodyFieldMap, bean);
// 拼装整个xml消息字符串
sbf.append(headStr).append(bodyStr);
sbf.append("</Msg_Body>");
}
catch (Exception e)
{
e.printStackTrace();
throw new HttpException("The bean conversion xml fail.", e);
}
return sbf.toString();
}
/**
* 根据传入的消息头字段拼装成xml格式字符串
*
* @param headListMap 消息头Field
* @param c 实体对象
* @return 拼装后的xml消息头字符串
* @throws IllegalAccessException 反射失败
*/
private static String buildHead(String version, String msgType, ListMap headListMap, Object c)
throws IllegalAccessException
{
// mod by wangzheng at 20100920 begin
// StringBuffer sbf = new StringBuffer("<head>");
StringBuffer sbf = new StringBuffer();
List<?> keyList = headListMap.getKeyList();
for (int i = 0; i < keyList.size(); i++)
{
String key = keyList.get(i).toString();
// 获取属性节点对应的消息节点名称
String msgFieldName = getMsgField(version, msgType, c.getClass().getName(), key);
msgFieldName = null == msgFieldName ? key : msgFieldName;
Field field = (Field)headListMap.get(key);
Object obj = field.get(c);
sbf.append("<").append(msgFieldName).append(">");
sbf.append(changeStrToXml(obj));
sbf.append("</").append(msgFieldName).append(">");
}
// sbf.append("</head>");
// mod by wangzheng at 20100920 begin
return sbf.toString();
}
/**
* 根据传入的消息体字段拼装成xml格式字符串
*
* @param bodyListMap 消息头Field
* @param c 实体对象
* @return 拼装后的xml消息体字符串
* @throws IllegalAccessException
*/
private static String buildBody(String version, String msgType, ListMap bodyListMap, Object c)
throws IllegalAccessException
{
// mod by wangzheng at 20100920 begin
// StringBuffer sbf = new StringBuffer("<body>");
StringBuffer sbf = new StringBuffer();
List<?> keyList = bodyListMap.getKeyList();
for (int i = 0; i < keyList.size(); i++)
{
String key = keyList.get(i).toString();
// 获取属性节点对应的消息节点名称
String msgFieldName = getMsgField(version, msgType, c.getClass().getName(), key);
msgFieldName = null == msgFieldName ? key : msgFieldName;
Field field = (Field)bodyListMap.get(key);
Object obj = field.get(c);
if (obj instanceof List)
{
String buildResult = Transform.buildList(version, msgType, (List<Object>)obj, msgFieldName);
sbf.append(buildResult);
}
else if (obj instanceof String[])
{
String buildResult = buildArray((String[])obj, msgFieldName);
sbf.append(buildResult);
}
else if (obj instanceof HttpInfo)
{
String buildResult = Transform.buildBean(version, msgType, obj);
sbf.append(buildResult);
}
else
{
sbf.append("<").append(msgFieldName).append(">");
sbf.append(changeStrToXml(obj));
sbf.append("</").append(msgFieldName).append(">");
}
}
// sbf.append("</body>");
// mod by wangzheng at 20100920 begin
return sbf.toString();
}
/**
* 根据传入的List消息体字段拼装成xml格式字符串
*
* @param list 消息实体对象列表
* @param listName 列表名称
* @return 拼装后的xml消息体字符串
* @throws IllegalAccessException
*/
private static String buildArray(String[] value, String listName)
throws IllegalAccessException
{
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < value.length; i++)
{
sbf.append("<").append(listName).append(">");
sbf.append(value[i]);
sbf.append("</").append(listName).append(">");
}
return sbf.toString();
}
/**
* 根据传入的List消息体字段拼装成xml格式字符串
*
* @param list 消息实体对象列表
* @param listName 列表名称
* @return 拼装后的xml消息体字符串
* @throws IllegalAccessException
*/
private static String buildList(String version, String msgType, List<Object> list, String listName)
throws IllegalAccessException
{
StringBuffer sbf = new StringBuffer();
sbf.append("<").append(listName).append(">");
for (int i = 0; i < list.size(); i++)
{
sbf.append(buildBean(version, msgType, list.get(i)));
}
sbf.append("</").append(listName).append(">");
return sbf.toString();
}
/**
* 把简单的实体对象中的属性转换成xml格式的字符串
*
* @param bean 简单的实体对象
* @return 转换后的字符串
* @throws IllegalAccessException
*/
private static String buildBean(String version, String msgType, Object bean)
throws IllegalAccessException
{
StringBuffer sbf = new StringBuffer();
Class<?> c = bean.getClass();
String path = c.getName();
//String className = path.substring(path.lastIndexOf(".") + 1, path.length());
//className = className.substring(0, className.indexOf("Info"));
String infoName = getMsgField(version, msgType, path);
infoName = null == infoName ? "" : infoName;
sbf.append("<").append(infoName).append(">");
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field f : fields)
{
String fieldName = f.getName();
// 只封装在配置文件中配置过的字段
if (isUseField(msgType, path, fieldName, version))
{
// 获取属性节点对应的消息节点名称
String msgFieldName = getMsgField(version, msgType, path, fieldName);
msgFieldName = null == msgFieldName ? fieldName : msgFieldName;
Object obj = f.get(bean);
if (obj instanceof List)
{
String buildResult = Transform.buildList(version, msgType, (List)obj, msgFieldName);
sbf.append(buildResult);
}
else
{
sbf.append("<").append(msgFieldName).append(">");
Object value = f.get(bean);
sbf.append(changeStrToXml(value));
sbf.append("</").append(msgFieldName).append(">");
}
}
}
sbf.append("</").append(infoName).append(">");
return sbf.toString();
}
private static boolean isUseField(String msgID, String infoName, String fieldName, String version)
{
// 根据消息ID从内存中取出发送消息配置Map
SendFieldInfo sendMsgInfo = HttpEnv.getSendMsgMap().get(version).get(msgID);
if (null != sendMsgInfo)
{
// 根据info的详细类名称取出发送消息字段
Map<String, MessageInfo> messageMap = sendMsgInfo.getMessageMap();
if (null != messageMap)
{
// 根据info路径获取配置的info
MessageInfo msgInfo = messageMap.get(infoName);
if (null != msgInfo)
{
Map<String, FieldInfo> fieldMap = msgInfo.getFieldMap();
// 根据消息字段获取匹配的属性字段
fieldName = fieldName.toLowerCase(Locale.getDefault());
FieldInfo fieldInfo = fieldMap.get(fieldName);
if (null != fieldInfo)
{