因为业务需要,传过来的是Xml报文,需要解析成JavaBean来进行详细操作
之前是用的将Xml报文转成Element节点递归遍历成一个map来操作使用,这样真的是太复杂冗余了,最终使用JAXBContenx工具来进行解析操作,更简单便捷
首先就是将报文解析成Xml
先导入所需要的的Maven依赖
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0-b170201.1204</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.0-b170127.1453</version>
</dependency>
主要还是用的Xml.bind这个包
然后就是代码:解析Xml为Javabean
被解析的对象需要添加@XmlRootElement
注解
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
/
**
* xml 解析成bean
* @param xmlString
* @param clazz
* @param <T>
* @return
*/
public static final <T> T xml2bean(String xmlString, Class<T> clazz) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (T) unmarshaller.unmarshal(new StringReader(xmlString));
} catch (JAXBException je) {
logger.error("解析xml失败,失败的bean是: {}", clazz);
logger.error("解析失败的xml是: {}", xmlString);
throw new UnsupportedOperationException(je);
}
}
bean转成Xml
public static final String bean2xml(Object object, Charset charset) {
String XML_DECLARATION_UTF8 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
String XML_DECLARATION_GBK = "<?xml version=\"1.0\" encoding=\"GBK\"?>";
String result = "";
JAXBContext context;
try {
context = JAXBContext.newInstance(object.getClass());
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
m.setProperty(Marshaller.JAXB_ENCODING, charset.name());
StringWriter writer = new StringWriter();
m.marshal(object, writer);
result = writer.toString();
result = (charset.name().equalsIgnoreCase("GBK") ? XML_DECLARATION_GBK : XML_DECLARATION_UTF8) + result;
return result;
} catch (JAXBException je) {
logger.info("转换失败,失败的bean是: {}", object.toString());
logger.info("转换失败的字符集是: {}", charset);
throw new UnsupportedOperationException(je);
}
}
测试
@RequestMapping("Xml")
public String Xml(@RequestBody String xmlString){
try {
JAXBContext jaxbContext = JAXBContext.newInstance(XmlFile.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
XmlFile xmlFile = (XmlFile)unmarshaller.unmarshal(new StringReader(xmlString));
System.out.println(xmlFile.getOrder().getAllPrice());
} catch (JAXBException je) {
throw new UnsupportedOperationException(je);
}
return null;
}
实体类的问题很关键,在根节点中也就是主类需要加上@XmlRootElement
并指定他的name也就是Xml报文中的根节点,在基本类型也就是没有子节点的属性名上加上@XmlAttribute
注解,如果Xml报文中有下划线的话,可能赋值不进来,得指定他的name对应一下;在引用数据属性上加上@XmlElment
注解,同样可以指定名字绑定,
以上就是Xml转JavaBean的操作
因为业务只用到了Xml转JavaBean而没有用到JavaBean转Xml所以,在这里只提一嘴,下次用的时候在补上
@Test
public void testJava2Xml(){
try {
JAXBContext jc = JAXBContext.newInstance(Man.class);
Marshaller ms = jc.createMarshaller();
Man man = new Man("man",100);
ms.marshal(man, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
出现具有两个相同属性的报错时,可能是因为解析类上没有加@XmlAccessorType(XmlAccessType.FIELD)
这个注解