在项目开发中有时要传输xm文件,要转换成字符串传输,而无法使用对象传输,所以要进行转换,所用进行总结下利用XStream进行string与XML对象之间的互转,以及在转换某一包下所有的类。
XML文件的解析和创建,请参考:http://blog.csdn.net/oyyz111/article/details/22730983
首先,利用Spring的PathMatchingResourcePatternResolver进行某包下的class文件的读取,其中用ant的匹配模式,例如congfig/**/*.class,是匹配config文件下一个目录或多个目录下的class文件,config/a/a.class或者config/a/b/b.class
代码如下:
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
public class AchieveFileUtils {
private static Logger logger = Logger.getLogger(AchieveFileUtils.class);
/**
* 获取某包下所有类的实例
* @param packagePath 包名
* @return class集合
*/
public static Set<Class<?>> getClasses(String packagePath){
Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
String packageClassPath = packagePath.replace(".", "/")+"/**/*.class" ;
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
Resource[] resources = resolver.getResources("classpath*:"+packageClassPath);
for(int i = 0;i < resources.length;i ++){
Resource resource = resources[i];
String completeFilePath = resource.getFile().getPath().replace(File.separator, "/");
logger.info("completeFilePath:"+completeFilePath);
String className = completeFilePath.substring(completeFilePath.lastIndexOf(packagePath.replace(".", "/")), completeFilePath.length()-6);
try {
classes.add(Class.forName(className.replace("/", ".")));
} catch (ClassNotFoundException e) {
logger.error("没有加载到此类");
logger.error(e.getMessage(), e.getCause());
}
logger.info("className:"+className);
}
} catch (IOException e) {
logger.error(e.getMessage(), e.getCause());
}
return classes;
}
}
XStream转换XML为对象,是需要对象的class的,所以前者获取class文件为后面的转换做铺垫
要转换的对象实例,User.java
@XStreamAlias("User") 表示别名
@XStreamAsAttribute 表示作为属性
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias("User")
public class User {
@XStreamAsAttribute
@XStreamAlias("ID")
private int id;
@XStreamAlias("Name")
@XStreamAsAttribute
private String name;
@XStreamAlias("PassWord")
@XStreamAsAttribute
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
private XStream xstream = new XStream(new XppDriver(newXmlFriendlyNameCoder("_-", "_")));
如果没有new XppDriver(new XmlFriendlyNameCoder("_-", "_")),,
别名取的是@XStreamAlias("ID_"),就被解析成@XStreamAlias("ID__")
xstream.processAnnotations(clazz);将要转换的class进行扫描
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Set;
import org.apache.log4j.Logger;
import com.frame.model.User;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
public class XStreamUtils {
private static Logger logger = Logger.getLogger(XStreamUtils.class);
private XStream xstream = new XStream(new XppDriver(
new XmlFriendlyNameCoder("_-", "_")));
public static XStreamUtils xStreamUtils = null;
/**
* 获取唯一的实例对象,通过双层锁
* @param packagePath 包名
* @return XStreamUtils对象
*/
public static XStreamUtils getInstance(String packagePath) {
if (xStreamUtils == null) {
synchronized (XStreamUtils.class) {
if (xStreamUtils == null) {
xStreamUtils = new XStreamUtils(packagePath);
}
}
}
return xStreamUtils;
}
/**
* 获取唯一的实例对象,通过双层锁
* @return XStreamUtils对象
*/
public static XStreamUtils getInstance(){
if(xStreamUtils == null){
synchronized (XStreamUtils.class) {
if(xStreamUtils == null)
xStreamUtils = new XStreamUtils();
}
}
return xStreamUtils;
}
/**
* XStreamUtils 构造方法
* @param packagePath
*/
private XStreamUtils(String packagePath) {
this.initXStream(packagePath);
}
/**
* 无参数构造
* XStreamUtils 构造方法
*/
private XStreamUtils() {
}
/**
* 根据传入的包名,将包下所有标有XStreamAlias注解的类进行扫描
* @param packagePath 包名
*/
private void initXStream(String packagePath) {
xstream.autodetectAnnotations(true);
Set<Class<?>> classes = AchieveFileUtils.getClasses(packagePath);
for (Class clazz : classes) {
Annotation annotation = clazz.getAnnotation(XStreamAlias.class);
if (annotation != null) {
xstream.processAnnotations(clazz);
} else {
for (Field field : clazz.getFields()) {
Annotation annotationFiled = field
.getAnnotation(XStreamAlias.class);
if (annotationFiled != null) {
xstream.processAnnotations(clazz);
break;
}
}
}
}
}
/**
* 将包下的object转换成string xml形式,object的class已经初始化了。
* @param obj 要转换的对象
* @return 字符串
*/
public String toXml(Object obj) {
return xstream.toXML(obj);
}
/**
* 将某一对象转换成string xml形式
* @param obj 要转换的对象
* @return 字符串的xml
*/
public String toXmlSingle(Object obj){
xstream.processAnnotations(obj.getClass());
return xstream.toXML(obj);
}
/**
* 将string的xml字符串转换成对象
* @param xml 要转换的string
* @param clazz 要转换成相应的clazz对象
* @return 转换后的对象
*/
public <T> T fromObjectSingle(String xml,Class<T> clazz){
xstream.processAnnotations(clazz);
T object = (T)xstream.fromXML(xml);
return object;
}
/**
* 将包下string的xml转换成对象,对象的class已经初始化
* @param xml 要进行转换的string
* @return 转换后的对象
*/
public Object fromObject(String xml) {
return xstream.fromXML(xml);
}
}
测试代码:
public static void main(String[] args) {
//XStreamUtils x = XStreamUtils.getInstance();
XStreamUtils x = XStreamUtils.getInstance("com.frame.model");
User user = new User();
user.setId(17);
user.setName("c");
user.setPassword("123");
//String stringXml = x.toXmlSingle(user);
String stringXml = x.toXml(user);
System.out.println(stringXml);
// User sUser = x.fromObjectSingle(stringXml, User.class);
User sUser = (User) x.fromObject(stringXml);
System.out.println(sUser.getName());
}
结果:
<User ID="17" Name="c" PassWord="123"/>
c