加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

XML处理利器:XStream

发布时间:2020-12-16 00:09:03 所属栏目:百科 来源:网络整理
导读:这篇博文参考《Spring 3.X 企业应用开发实战》第14章内容,加了一下自己的理解,自己的应用。 在开发过程中,总是会需要一些配置文件。如果只需要一个配置文件的话还好说,但是在企业开发中往往需要2个或多个配置文件,这岂不是要写多个配置文件的读操作。缺

这篇博文参考《Spring 3.X 企业应用开发实战》第14章内容,加了一下自己的理解,自己的应用。
在开发过程中,总是会需要一些配置文件。如果只需要一个配置文件的话还好说,但是在企业开发中往往需要2个或多个配置文件,这岂不是要写多个配置文件的读操作。缺点如下:
a. 配置文件较多,配了这个忘记那个,麻烦。
b.代码写起来复杂,冗余。
c.。。。。
因此,可以使用XML一个配置文件来配置。

XStream概述

XStream是一个简洁的开源框架,可以将java对象序列化为XML或者将XML反序列化java对象。除了java对象与XML之间的相互转换之外,XStream还可以实现java对象与Json之间的相互转换。但是,实际使用中还是使用Jackson框架的比较多。关于Jackson框架以及一个封装好的JacksonUtil源码,详见Jackson框架及JacksonUtil源码(记得之前写过但是现在不知怎么没了,有空补上)。
XStream的框架组成主要包括4部分:Converters(转换器)、IO(输入输出)、Context(上线文引用)、Facade(统一入口)。
(1)Converters转化器
我们在XML中的配置都是字符,怎么能将字符转换成基本数据类型(boolean,byte,char,short,int,long,float,double)呢?以及这个的反过程是怎么做的?使用的就是这个Converters转换器。XStream为通用类型提供了多中转换器实现,包括基本数据类型、String、Collections、Arrays、null、Date等。程序猿也可以为特定需求量身定制Converters,只需要实现Converter接口就可以。如将“2016年1月27日 星期三”转换成Date类型。这里不再赘述,理解的不是太深,有空独辟一篇阐述吧。
(2)IO输入输出
这个不是太懂。需要理解一些java IO的东西,这个我很欠缺。下一步打算看看《Think in Java》中的IO部分和并发部分(之所以要看并发是因为写完这篇博文之后要写quartz)。先复述一下书吧。
XStream给出了java.io.ObjectInputStream和java.io.ObjectOutputStream的替代实现,允许以对象流(到底什么才是流?)的方式进行XML序列化和反序列化。XStream通过接口HierarchicalStreamWriter和HierarchicalStreamReader分别实现序列化和反序列化。XStream为HierarchicalStreamWriter接口实现了几种实现,如CompactWriter,PrettyPrintWriter。其中,CompactWriter输出的为连续的没有分隔的XML文件,而PrettyPrintWriter输出的是有分隔有一定格式的XML文件。
(3)Context(上下文引用)
XStream在序列化和反序列化时,会创建两个类MarshallingContext和UnmarshallingContext,由它们来处理数据并委派合适的Converter。
(4)Facade(统一入口)
Facade将上面三个重要组件集成在一起,以统一的接口开放出来。

终于把不懂的东西写完了,终于可以写干货了。

应用XStream解析XML配置文件

比方,有一种应用即要配置白名单又要配置黑名单。如白名单用于测试人员各种测试折腾,黑名单用于用户将某好友列为黑名单。配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<TypeConfigs>
    <TypeConfig>
        <type>1</type>
        <datas>
            <long>123</long>
            <long>321</long>
        </datas>
    </TypeConfig>

    <TypeConfig>
        <type>2</type>
        <datas>
            <long>7777</long>
            <long>888888</long>
            <long>999999999</long>
        </datas>
    </TypeConfig>
</TypeConfigs>

其中type 1表示白名单,type 2表示黑名单。datas表示uid列表。

TypeConfig.java

package org.fan.test.xstream;

import java.util.List;

/** * Created by fan on 16-1-18. */
public class TypeConfig {
    int type;
    //String datas;
    long[] datas;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public long[] getDatas() {
        return datas;
    }

    public void setDatas(long[] datas) {
        this.datas = datas;
    }

}

TypeConfigList.java

package org.fan.test.xstream;

import java.util.List;

/** * Created by fan on 16-1-18. */
public class TypeConfigList {
    List<TypeConfig> typeConfigList;

    public List<TypeConfig> getTypeConfigList() {
        return typeConfigList;
    }

    public void setTypeConfigList(List<TypeConfig> typeConfigList) {
        this.typeConfigList = typeConfigList;
    }
}

XmlParserTest.java

package org.fan.test.xstream;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import java.io.FileInputStream;
import java.io.FileNotFoundException;


/** * Created by fan on 16-1-27. */
public class XmlParserTest {

    XStream xStream = new XStream(new DomDriver());
    TypeConfigList typeConfigList;

    public static void main(String[] args) {
        final XmlParser xmlParser = new XmlParser();

        xmlParser.xStream.alias("TypeConfigs",TypeConfigList.class);
        xmlParser.xStream.alias("TypeConfig",TypeConfig.class);

        xmlParser.xStream.addImplicitCollection(TypeConfigList.class,"typeConfigList");
        //xmlParser.xStream.addImplicitCollection(TypeConfig.class,"datas");

        xmlParser.readConfigFile();
        System.out.println("YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY");

    }

    public void readConfigFile() {
        String path = XmlParser.class.getResource("/").getPath();
        FileInputStream pusherInputStream = null;
        try {
            pusherInputStream = new FileInputStream(path + "config.xml");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        typeConfigList = (TypeConfigList) xStream.fromXML(pusherInputStream);
        for (TypeConfig typeConfig : typeConfigList.getTypeConfigList()) {
            long[] datas = typeConfig.getDatas();
            for (int i = 0; i < datas.length; i++) {
                System.out.println(datas[i]);
            }
        }
    }
}

需要解释的几点:
1.XML解析器

XStream xStream = new XStream(new DomDriver());

DomDriver为XML解析引擎,这种方式会将整个XML文档读入到内存造成较大的内存开销。可以使用如下方式,采用XPP(XML Pull Parse)。XPP是一种快速解析XML的解析器。

XStream xStream = new XStream();

2.使用XStream别名

xmlParser.xStream.alias("TypeConfigs",TypeConfigList.class);
xmlParser.xStream.alias("TypeConfig",TypeConfig.class);

如果不是别名,则将java对象转换成XML时,根节点会是完整的类名,阅读起来不够方便、自然。
通过alias方法可以将类名在XML中的展现变成别名。还可以对类中的属性设置别名,如:

aliasField(String alias,Class defineIn,String fieldName);

还可以将类中的属性作为XML中的属性存在。这个比较难理解。

aliasAttribute(Class defineIn,String attributeName,String alias);

如,将TypeConfig类中的type当成XML中TypeConfig结点的属性,则可以如下实现:

aliasAttribute(TypeConfig.class,"type","typeA");

其中,”type”是TypeConfig类中的属性名,typeA是结点TypeConfig的属性。
只是单独设置了别名还不会起作用,还需要将这个改变作用到这个类的属性上。

useAttributeFor(Class defineIn,String fieldName);
useAttributeFor(TypeConfig.class,"type");

这样在XML中的呈现方式是:

<TypeConfig type="1">

3.当类中有list之类的属性时

xmlParser.xStream.addImplicitCollection(TypeConfigList.class,"typeConfigList");

如果没有调用上面的方法(addImplicitCollection,增加隐式集合),则XML中需要这样写:

<TypeConfigs>
    <typeConfigList>
        <TypeConfig>
            <type>1</type>
            <datas>
                <long>123</long>
                <long>321</long>
            </datas>
        </TypeConfig>

        <TypeConfig>
            <type>2</type>
            <datas>
                <long>7777</long>
                <long>888888</long>
                <long>999999999</long>
            </datas>
        </TypeConfig>
    </typeConfigList>
</TypeConfigs>

上面的这个看上去很多余。所以调用addImplicitCollection方法可以使XML更简洁。
4.序列化和反序列化

//反序列化
fromXML(inputStream);
//序列化
toXML(javaObject,outputStream);

待续

1.别名注解 2.XStream四大组件的详解 3.实际开发需求 有时配置文件不可能只配置一次,有可能而且是大多数情况下都是临时加各种配置参数。总不能每次都重启服务,重新读取配置文件吧。因此,如果能每过一段时间就能读取下配置文件就好了,这就是下篇博文要解决的问题。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读