在项目开发中有时要传输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