XStream是一个实现javaBean与XML相互转换的工具极大地简化了开发人员的对XML的处理
1、添加依赖
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.11.1</version> </dependency>
2、UML类图
<Document TaskGuid="560eec8a-be14-4398-8c9a-73b68651a129" DataGuid="" DataType=" QueryJYYKTByHourList" > <Data> <KBH Type="TEXT">卡编号</KBH> <DEALRQ Type="TEXT">刷卡日期</DEALRQ> <DEALSJ Type="TEXT">刷卡时间</DEALSJ> <XLBM Type="TEXT">线路编码</XLBM> </Data> <Data> <KBH Type="TEXT">卡编号</KBH> <DEALRQ Type="TEXT">刷卡日期</DEALRQ> <DEALSJ Type="TEXT">刷卡时间</DEALSJ> <XLBM Type="TEXT">线路编码</XLBM> </Data> …重复数据 </Document>
假设现在需要将以上假设xml转换为一个JavaBean,所以首先要分析这一点XML根节点是结构Document,有三个属性TaskGuid、DataGuid、DataType,有许多个子节点Data,每个Data节点有四个子节点:KBH、DEALRQ、DEALSJ、XLBM。可以用这个想法:用一个Document类:有四个字段,TaskGuid、DataGuid、DataType与一个Data的集合。每一个Data有四个字段:KBH、DEALRQ、DEALSJ、XLBM,每个字段都有一个Type和一个值。
UML类图如下:

Document和Data是聚合关系,Data脱离了Document独立存在,Data和Kbh、Dealrq、Dealsj与Xlbm是组合关系,了组合关系Data不能独立存在。
3、XStream注解
在输出XML忽略属性设置转换器 converter它主要用于在一个类别中写下一些字段的复杂转换。 然后注册XStream。
工具类
public class XsteamUtil { public static Object toBean(Class<?> clazz, String xml) { Object xmlObject = null; XStream xstream = new XStream(); xstream.processAnnotations(clazz); xstream.autodetectAnnotations(true); xmlObject= xstream.fromXML(xml); return xmlObject; } }
在SpringBoot中可以使用@Bean来进行IOC,设置xstream.autodetectAnnotations(true);来处理注解
如果要进行xml转JavaBean需要设施的操作xstream.alias()
4、具体使用
ReturnResult.java
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; import lombok.Data; import lombok.ToString; import lombok.experimental.Accessors; import java.util.List; @Data @ToString @Accessors(chain = true) @XStreamAlias("Document") public class ReturnResult { @XStreamAlias("TaskGuid") @XStreamAsAttribute private String taskGuid; @XStreamAlias("DataGuid") @XStreamAsAttribute private String dataGuid; @XStreamAlias("DataType") @XStreamAsAttribute private String dataType; @XStreamImplicit private List<Record> records; }
使用了@XStreamAlias注释给类和字段的别名,ReturnResult对应根节点Document,Java代码中的变量名提倡小写驼峰命名,所以我也使用字段的别名。@XStreamAsAttribute以字段为属性而不是节点。@XStreamImplicit根节点不显示最外层的集合。
Record.java
import com.thoughtworks.xstream.annotations.XStreamAlias; import lombok.Data; import lombok.experimental.Accessors; @Data @Accessors(chain = true) @XStreamAlias("Data") public class Record { @XStreamAlias("KBH") private CardNo cardNo; @XStreamAlias("DEALRQ") private DealDate dealDate; @XStreamAlias("DEALSJ") private DealTime dealTime; @XStreamAlias("XLBM") private RouteCode routeCode; }
由于XML文件的节点名不够知名,所以我用@XStreamAlias解决方法。
CardNo.java
import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamConverter; import com.thoughtworks.xstream.converters.extended.ToAttributedValueConverter; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; /**
* @author huwen
* 卡编号
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
@XStreamAlias("KBH")
@XStreamConverter(value= ToAttributedValueConverter.class, strings={"value"})
public class CardNo {
@XStreamAlias("Type")
private String type;
private String value;
}
一个<KBH Type="TEXT">卡编号</KBH>节点既有属性又有值,所以使用了@XStreamConverter,用xstream自带的转换器进行转换。
@Test
public void testReturnResult2(){
XStream xStream = new XStream();
//由于使用的注解,将自动检测注解开启
xStream.autodetectAnnotations(true);
List<Record> records = new ArrayList<>();
//设置对象的属性值
CardNo k1 = new CardNo().setType("TEXT").setValue("36283723");
CardNo k2 = new CardNo().setType("TEXT").setValue("121211");
DealTime dealTime1 = new DealTime().setType("TEXT").setValue("12");
DealTime dealTime2 = new DealTime().setType("TEXT").setValue("1");
DealDate dealDate1 = new DealDate().setType("TEXT").setValue("20200617");
DealDate dealDate2 = new DealDate().setType("TEXT").setValue("20200520");
RouteCode routeCode1 = new RouteCode().setType("TEXT").setValue("212");
RouteCode routeCode2 = new RouteCode().setType("TEXT").setValue("112");
records.add(new Record().setCardNo(k1).setDealDate(dealDate1).setDealTime(dealTime1).setRouteCode(routeCode1));
records.add(new Record().setCardNo(k2).setDealDate(dealDate2).setDealTime(dealTime2).setRouteCode(routeCode2));
ReturnResult result = new ReturnResult().setDataType("QueryJYYKTByHourList").setTaskGuid("560eec8a-be14-4398-8c9a-73b68651a129")
.setDataGuid("d78whe28eh").setRecords(records);
//转换为xml格式的字符串
String s = xStream.toXML(result);
String s1 =
"<Document TaskGuid=\"560eec8a-be14-4398-8c9a-73b68651a129\" DataGuid=\"d78whe28eh\" DataType=\"QueryJYYKTByHourList\">\n" +
" <Data>\n" +
" <KBH Type=\"TEXT\">36283723</KBH>\n" +
" <DEALRQ Type=\"TEXT\">20200617</DEALRQ>\n" +
" <DEALSJ Type=\"TEXT\">12</DEALSJ>\n" +
" <XLBM Type=\"TEXT\">212</XLBM>\n" +
" </Data>\n" +
" <Data>\n" +
" <KBH Type=\"TEXT\">121211</KBH>\n" +
" <DEALRQ Type=\"TEXT\">20200520</DEALRQ>\n" +
" <DEALSJ Type=\"TEXT\">1</DEALSJ>\n" +
" <XLBM Type=\"TEXT\">112</XLBM>\n" +
" </Data>\n" +
"</Document>";
System.out.println(s);
System.out.println(xStream.fromXML(s1));
}
上面的例子将JavaBean转换为xml。
@Test
public void testReturnData(){
XStream xStream = new XStream();
xStream.autodetectAnnotations(true);
//必须要加这行代码,否则会报错,找不到这个类
xStream.alias("Document",ReturnResult.class);
String s = "<Document TaskGuid=\"560eec8a-be14-4398-8c9a-73b68651a129\" DataGuid=\"dhshdisds89e\" DataType=\"QueryJYYKTByHourList\">\n" +
" <Data>\n" +
" <KBH Type=\"TEXT\">12121</KBH>\n" +
" <DEALRQ Type=\"TEXT\">2020212</DEALRQ>\n" +
" <DEALSJ Type=\"TEXT\">12</DEALSJ>\n" +
" <XLBM Type=\"TEXT\">12</XLBM>\n" +
" </Data>\n" +
" <Data>\n" +
" <KBH Type=\"TEXT\">37612</KBH>\n" +
" <DEALRQ Type=\"TEXT\">2020312</DEALRQ>\n" +
" <DEALSJ Type=\"TEXT\">15</DEALSJ>\n" +
" <XLBM Type=\"TEXT\">23</XLBM>\n" +
" </Data>\n" +
"</Document>";
System.out.println(xStream.fromXML(s));
}
上面的例子将xml形式的字符串转换为JavaBean,需要注意的是必须要加这行代码,否则会报这个异常。
可以看出使用XStream的一般步骤:
- 创建XStream对象:XStream xStream = new XStream();
- 开始自动检测注解:xStream.autodetectAnnotations(true);
- 进行转换:fromXML或者toXML
既让这个XStrem对象经常使用,那么在Spring项目中可以使用Spring IOC将它交给Spring容器进行管理,在需要的时候进行注入即可。