前言
由于项目需要,调用第三方接口,接口返回格式为xml格式。遂用上了javax.xml 用于实现Bean和xml互转
首先我们看看工具类XmlUtil
/** * XML转对象 * * @param xmlStr xml字串 * @param t 对象类型 * @return 对象 */ public static <T> T xmlToBean(String xmlStr, Class<T> t) { try { //特殊字符不让其转义,不然会报错 if (xmlStr.contains("")) { xmlStr = xmlStr.replace("","<![CDATA[]]>"); } JAXBContext context = JAXBContext.newInstance(t); Unmarshaller unmarshaller = context.createUnmarshaller(); StringReader reader = new StringReader(xmlStr); SAXParserFactory sax = SAXParserFactory.newInstance(); //设置忽略命名空间 sax.setNamespaceAware(false); XMLReader xmlReader = sax.newSAXParser().getXMLReader(); Source source = new SAXSource(xmlReader, new InputSource(reader)); return (T) unmarshaller.unmarshal(source); } catch (JAXBException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } return null; } /** * 对象转XML * * @param obj 对象 * @return 字符串 */ public static String beanToXml(Object obj) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { JAXBContext context = JAXBContext.newInstance(obj.getClass()); Marshaller marshaller = context.createMarshaller(); // marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE); marshaller.marshal(obj, out); try { return new String(out.toByteArray(), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } catch (JAXBException e) { e.printStackTrace(); } return null; }
代码解释
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
如果为true的话,则不会生成<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
使用的Bean
@XmlRootElement(name = "requestXML") @XmlAccessorType(XmlAccessType.FIELD) public class TelefenCommonVO { /** * 应用编码 */ @XmlElement(name = "AppID") private String appid; /** * 接入业务 */ private String SPID; /** * 请求流水 */ private String RequestNo; /** * 请求时间 */ private String RequestTime; /** * 签名 */ @XmlTransient private String Sign; public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } public String getSPID() { return SPID; } public void setSPID(String SPID) { this.SPID = SPID; } public String getRequestNo() { return RequestNo; } public void setRequestNo(String requestNo) { RequestNo = requestNo; } public String getRequestTime() { return RequestTime; } public void setRequestTime(String requestTime) { RequestTime = requestTime; } public String getSign() { return Sign; } public void setSign(String sign) { this.Sign = sign; } public TelefenCommonVO() { } protected TelefenCommonVO(Builder builder) { this.appid = builder.AppID; this.SPID = builder.SPID; this.RequestNo = builder.RequestNo; this.RequestTime = builder.RequestTime; this.Sign = builder.Sign; } public static final class Builder{ /** * 应用编码 */ private String AppID; /** * 接入业务 */ private String SPID; /** * 请求流水 */ private String RequestNo; /** * 请求时间 */ private String RequestTime; /** * 签名 */ private String Sign; public Builder setAppID(String appID) { this.AppID = appID; return this; } public Builder setSPID(String SPID){ this.SPID = SPID; return this; } public Builder setRequestNo(String requestNo){ this.RequestNo = requestNo; return this; } public Builder setRequestTime(String requestTime){ this.RequestTime = requestTime; return this; } public Builder setSign(String sign){ this.Sign = sign; return this; } public TelefenCommonVO build() { return new TelefenCommonVO(this); } } }
代码解释
@XmlRootElement(name = "requestXML") 注解是指定xml的根节点,作用在类上
@XmlAccessorType 用于指定有java对象生成xml文件时对java对象属性的访问方式。 它的属性值是XmlAccessType的四个枚举值。分别是:
XmlAccessType.FIELD java 对象中的所有成员变量
XmlAccessType.PROPERTY java对象中所有通过getter/setter 方式访问的成员变量。
XmlAccessType.PUBLIC_MEMBER java 对象中所有的public 访问权限的成员变量和通过getter/setter方式访问的成员变量 。
XmlAccessType.NONE java对象的所有属性都不映射为XML元素
@XmlElement
该注解用在类的属性上。用于将属性映射为xml的子节点,可通过在后面配置name属性值类改变java属性在xml文件中的名称。例如:
@XmlElement(name = "AppID") private String appid;
转化成xml为<AppID></AppID> 而不是<appid></appid>
5. @XmlAccessorOrder
用于对java 对象生成的xml元素进行排序。它有两个属性值:
AccessorOrder.ALPHABETICAL:对生成的xml元素按字母顺序排序;
XmlAccessOrder.UNDEFINED:不进行排序
6. @XmlTransient
用于标示在由java对象映射xml时,忽略此属性。即,在生成的xml文件中不出现此元素。
7. @XmlElementWrapper
在注解最外面再加一层,可用于POJO中包含List的属性中,例如:
待转化sql
<responseXML> <Details> <Detail> <CardNo>11111</CardNo> <CardPwd>2222</CardPwd> <CodeURL/> </Detail> </Details> </responseXML>
对应的Bean
@XmlRootElement(name ="responseXML") @XmlAccessorType(XmlAccessType.FIELD) public class OrderPayRespVO { /** * 卡信息列表 */ @XmlElementWrapper(name="Details") @XmlElement(name = "Detail") private List<Detail> Details; 省略get,set方法 }
@XmlRootElement(name = "Detail") @XmlAccessorType(XmlAccessType.FIELD) public class Detail { /** * 卡号 */ private String CardNo; /** * 卡密 */ private String CardPwd; /** * 短链 */ private String CodeURL; 省略get,set方法 }
转化之后
OrderPayRespVO{Details=[Detail{CardNo='11111', CardPwd='2222', CodeURL=''}]}
此外该Bean 还使用到了建造者设计模式来实现属性的链式调用。
测试代码
public static void main(String[] args) throws IOException { TelefenCommonVO commonVO = new TelefenCommonVO.Builder() .setAppID("1112") .setRequestNo("3333") .setSPID("444") .setRequestTime("20180823") .setSign("qqwqwqwq1121") .build(); String xml = beanToXml(commonVO); System.out.println("返回的xml为="+xml); TelefenCommonVO commonVO1 = xmlToBean(xml, TelefenCommonVO.class); System.out.println("转化后的bean为="+commonVO1.toString()); }
运行结果
返回的xml为=<?xml version="1.0" encoding="UTF-8" standalone="yes"?><requestXML><AppID>1112</AppID><SPID>444</SPID><RequestNo>3333</RequestNo><RequestTime>20180823</RequestTime></requestXML> 转化后的bean为=TelefenCommonVO{appid='1112', SPID='444', RequestNo='3333', RequestTi