XStream是一个实现javaBean与XML互相转换的工具,极大地简化了开发人员的对XML的处理
1、添加依赖
com.thoughtworks.xstream
xstream
1.4.11.1
2、UML类图
卡编号
刷卡日期
刷卡时间
线路编码
卡编号
刷卡日期
刷卡时间
线路编码
…数据重复出现
假设现在需要将上面的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注解
主要使用
@XStreamAlias(“alis”)
java对象在xml中以标签的形式显示时,如果名字与类名或者属性名不一致,可以使用该标签并在括号内注明别名。
@XStreamOmitField
在输出XML的时候忽略该属性
@XStreamImplicit
如果该属性是一个列表或者数组,在XML中不显示list或者Array字样
@XStreamAsAttribute
该属性不单独显示成XML节点,而是作为属性显示出来
@XStreamConverter
设置转换器
@XStreamConverters
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 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;
}
一个
节点既有属性又有值,所以使用了@XStreamConverter
,用xstream自带的转换器进行转换。
@Test
public void testReturnResult2(){
XStream xStream = new XStream();
//由于使用的注解,将自动检测注解开启
xStream.autodetectAnnotations(true);
List 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 =
"\n" +
" \n" +
" 36283723 \n" +
" 20200617 \n" +
" 12 \n" +
" 212 \n" +
" \n" +
" \n" +
" 121211 \n" +
" 20200520 \n" +
" 1 \n" +
" 112 \n" +
" \n" +
" ";
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 = "\n" +
" \n" +
" 12121 \n" +
" 2020212 \n" +
" 12 \n" +
" 12 \n" +
" \n" +
" \n" +
" 37612 \n" +
" 2020312 \n" +
" 15 \n" +
" 23 \n" +
" \n" +
" ";
System.out.println(xStream.fromXML(s));
}
上面的例子将xml形式的字符串转换为JavaBean,需要注意的是必须要加xStream.alias("Document",ReturnResult.class);这行代码,否则会报com.thoughtworks.xstream.mapper.CannotResolveClassException: Document这个异常。
可以看出使用XStream的一般步骤:
- 创建XStream对象:XStream xStream = new XStream();
- 开始自动检测注解:xStream.autodetectAnnotations(true);
- 进行转换:fromXML或者toXML
既让这个XStrem对象经常使用,那么在Spring项目中可以使用Spring IOC将它交给Spring容器进行管理,在需要的时候进行注入即可。