美文网首页
Xstream工具类整合

Xstream工具类整合

作者: 花花大脸猫 | 来源:发表于2021-08-27 16:57 被阅读0次

由于工作背景以及行业原因,与外部业务系统的交互基本都是基于XML报文格式进行处理,原先通过老的dom4j等框架的解析效率太低且复用性较差,最大的原因在于代码的可读性以及可维护性,所以后续基于xstream的框架写了一个工具类,提供给各组件使用,为后续接入也是基于XML交互的外部系统提供很大的开发便利,具体的代码如下:

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

import java.io.Writer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * xml对象转换工具类
 *
 * @author 花花大脸猫
 * @data
 */
public final class XmlUtil {
    private final static Map<Class<?>, XStream> XSTREAM_HOLDER = new ConcurrentHashMap<>();

    private final static HierarchicalStreamDriver DRIVER = new XppDriver() {
        @Override
        public HierarchicalStreamWriter createWriter(Writer out) {
            return new EscapeCharWriter(out);
        }
    };

    /**
     * 一般用法,直接生成对象信息
     *
     * @param cls
     * @return
     */
    private static XStream getXstream(Class<?> cls) {
        return XSTREAM_HOLDER.computeIfAbsent(cls, t -> {
            XStream xstream = new XStream(DRIVER);
            xstream.processAnnotations(t);
            xstream.allowTypes(new Class[]{t});
            xstream.ignoreUnknownElements();
            return xstream;
        });
    }

    /**
     * 对象中存在泛型时候调用的方法
     *
     * @param cls                      父类
     * @param subClasses               子类
     * @param classContainsGenericType 包含泛型类的类
     * @return
     */
    private static XStream getXstream(Class<?> cls, Class[] subClasses, Class<?> classContainsGenericType) {
        return XSTREAM_HOLDER.computeIfAbsent(cls, t -> {
            XStream xstream = new XStream(DRIVER);
            xstream.processAnnotations(t);
            xstream.processAnnotations(subClasses);
            for (Class subClass : subClasses) {
                try {
                    xstream.addDefaultImplementation(subClass, classContainsGenericType.getDeclaredField("t").getType
                            ());
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                    break;
                }
            }
            xstream.allowTypes(new Class[]{t});
            xstream.allowTypes(subClasses);
            xstream.ignoreUnknownElements();
            return xstream;
        });
    }


    /**
     * 将java object对象转换为xml串,不包含xml头字符串
     *
     * @param obj
     * @return
     */
    public static String objectToXml(Object obj) {
        return getXstream(obj.getClass()).toXML(obj);
    }

    /**
     * 将java object对象转换为xml串,不包含xml头字符串
     * 此方法用于转换对象中存在泛型的情况处理
     *
     * @param obj
     * @return
     */
    public static String objectToXml(Object obj, Class[] subClasses, Class classContainsGenericType) {
        return getXstream(obj.getClass(), subClasses, classContainsGenericType).toXML(obj);
    }

    /**
     * 将java object对象转换为xml串,包含xml头字符串,并指定xml编码
     *
     * @param obj
     * @param charSet
     * @return
     */
    public static String objectToXml(Object obj, String charSet, Class[] subClasses, Class classContainsGenericType) {
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"")
                .append(charSet.toUpperCase())
                .append("\"?>\n").append(objectToXml(obj, subClasses, classContainsGenericType));
        return sb.toString();
    }

    /**
     * 将java object对象转换为xml串,包含xml头字符串,并指定xml编码
     * 此方法用于转换对象中存在泛型的情况处理
     *
     * @param obj
     * @param charSet
     * @return
     */
    public static String objectToXml(Object obj, String charSet) {
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"")
                .append(charSet.toUpperCase())
                .append("\"?>\n").append(objectToXml(obj));
        return sb.toString();
    }

    /**
     * 将给定的xml串转换为对应的class类
     *
     * @param xml
     * @param cls
     * @param <T>
     * @return
     */
    public static <T> T xmlToObject(String xml, Class<T> cls) {
        return (T) getXstream(cls).fromXML(xml);
    }


    /**
     * Xstream 转换器帮助类,过滤写入xml串内的所有特殊字符,
     * 默认的 PrettyPrintWriter中会对特殊字符进行转义处理
     *
     * @author 花花大脸猫
     * @date
     */
    static class EscapeCharWriter extends PrettyPrintWriter {
        public EscapeCharWriter(Writer writer) {
            super(writer);
        }

        /**
         * 不对节点标签中存在的特殊字符进行转换,避免出现“双下划线”
         *
         * @param name
         * @return
         */
        @Override
        public String encodeNode(String name) {
            return name;
        }

        @Override
        protected void writeText(QuickWriter writer, String text) {
            if (text.indexOf('<') < 0) {
                writer.write(text);
            } else {
                writer.write("<[CDATA[");
                writer.write(text);
                writer.write("]]>");
            }
        }
    }
}

目前采用的xstream的版本为1.4.10,上述工具类可能还有不足之处,如有问题,希望不吝指出,多谢。

相关文章

网友评论

      本文标题:Xstream工具类整合

      本文链接:https://www.haomeiwen.com/subject/biimiltx.html