研发过程中遇到的坑坑洼洼
很多时候我们不仅要解析json格式的数据,xml也是一种很常见的数据格式,很多老的系统都采用的这种方式,我们要与之通讯和交换数据就必须做数据转换,XStream很方便的实现了bean和xml的互转,而且性能非常优越,应该xml都会选择XStream,虽然好用也会有一些小坑。
请看如下程序步骤
一、情况:通过XStream把xml数据转换成Statusbox对象列表返回
XStream xstream = new XStream();
xstream.alias("returnsms", ArrayList.class);
xstream.alias("statusbox", Statusbox.class);//把XML解析为Statusbox对象返回
return (List<Statusbox>) xstream.fromXML(in);
二、在业务层调用的时候
List<Statusbox> statusboxList = shortMessage.getReport();
for (int i = 0; i < statusboxList.size(); i++) {
Statusbox statusbox = statusboxList.get(i); // 这里就报错了
}
Statusbox statusbox = statusboxList.get(i); // 这里就报错了看一下错误
三、竟然报错了,看了错误肯定会觉得很困惑
Caused by: java.lang.ClassCastException: com.project.tool.sms.Statusbox cannot be cast to com.project.tool.sms.Statusbox
1、com.project.tool.sms.Statusbox
2、com.project.tool.sms.Statusbox
两个相同的类既然不能转,在单独的测试类中测试也是没问题的,但是一发布到生产环境就报错。这是为什么呢?
解决方法
原因我们运用的是Springboot采用的类加载器(ClassLoader)的同时,XStream也用在用自己的类加载器。当两个不同的ClassLoader对象加载具有相同名称的类时(Java中两个类的相等性取决于加载它的完全名称和类加载器)
因此,如果两个独立的类加载器从同一位置加载类,那么这些类型的对象将无法转换为彼此的类型。
XStream xstream = new XStream();
xstream.setClassLoader(getClass().getClassLoader());
xstream.alias("returnsms", ArrayList.class);
xstream.alias("statusbox", Statusbox.class);//把XML解析为Statusbox对象返回
return (List<Statusbox>) xstream.fromXML(in);
添加了一行 xstream.setClassLoader(getClass().getClassLoader());
让XStream采用和Springboot同一个类加载器即可。