jaxb实现xml和java对象互转

最近遇到了调用接口需要xml报文传递,用传统最简单的方式就是我们string手动拼接报文传递,这样调用问题解决了,返回的数据问题没有得到解决,因为返回的也是xml报文,需要对其做一些转换操作,既然转换,直接在传递时通过简单的方式将报文序列化为指定编码格式的xml,然后返回时再互转就可以,这样第一代码结构清晰,第二这种行为看起来貌似也比较优雅。

我有看过利用dom4j和实现xml和json之间的转换,最终执行时,采用注解+实体的方式来实现效果比较乐观点。

pom依赖:

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>

 建立对应的实体,这个实体需要和对应的xml来映射。由于我们可能会用到同一个请求头,所以可以吧请求头作为一个公共的实体,其他对应实体继承父类就好,比如有如下报文:

<?xml version="1.0" encoding="GB2312" standalone="yes" ?> 
<TX> 
  <REQUEST_SN></REQUEST_SN> 
  <CUST_ID></CUST_ID> 
  <USER_ID></USER_ID> 
  <PASSWORD></PASSWORD> 
  <TX_CODE></TX_CODE> 
  <LANGUAGE></LANGUAGE> 
  <TX_INFO> 
  </TX_INFO> 
</TX 

其父类:

package com.haohuo.account.util.ccb.bean.req;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(propOrder = { "requestSn","custId", "userId", "password","txCode","language" })
public class RequestHeaderBean{

	@XmlElement(name = "REQUEST_SN", required = true)
	private String requestSn;
	@XmlElement(name = "CUST_ID", required = true)
	private String custId;
	@XmlElement(name = "USER_ID", required = true)
	private String userId;
	@XmlElement(name = "PASSWORD", required = true)
	private String password;
	@XmlElement(name = "TX_CODE", required = true)
	private String txCode;
	@XmlElement(name = "LANGUAGE", required = true)
	private String language;
	
	//get set略
}

 这里说明一下,父类是根据众多xml提取出来的,此例只是用来做个简单样例,这里会用到几个注解,简单介绍几个:

XmlAccessorType  
默认规则: 
默认情况下,如果包中不存在 @XmlAccessorType,那么假定使用以下包级别注释。 
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) 
默认情况下,如果类中不存在 @XmlAccessorType,并且没有任何超类是使用 @XmlAccessorType 注释的,则假定在类中使用以下默认注释: 
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) 
可能值: 
FIELD:    JAXB 绑定类中的每个非静态、非瞬态字段将会自动绑定到 XML,除非由 XmlTransient 注释。 
NONE:     所有字段或属性都不能绑定到 XML,除非使用一些 JAXB 注释专门对它们进行注释。 
PROPERTY: JAXB 绑定类中的每个获取方法/设置方法对将会自动绑定到 XML,除非由 XmlTransient 注释。 
PUBLIC_MEMBER:每个公共获取方法/设置方法对和每个公共字段将会自动绑定到 XML,除非由 XmlTransient 注释。

@XmlRootElement:根节点

@XmlElement:该属性作为xml的element,且可以增加属性(name="NewElementName"),那么生成的xml串的elment的标签是NewElementName

@XmlType:该注解通过属性propOrder来设置文件各个属性的输出属性,值为bean的属性值。

看子类

package com.haohuo.account.util.ccb.bean.req;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name="TX")
public class RequestSelectCode extends RequestHeaderBean implements Serializable {

    @XmlElement(name = "TX_INFO" , required = false)
    private String txInfo;

   
    //get set 略
}

这里需要注意的是,@XmlRootElement,只在子类中声明就可以了,父类中不需要声明,否则在xml转对应实体时会有异常,说白了,就是此注解在一个报文组成中只能出现一次。

然后就上一个xml和实体互转的工具类

package com.haohuo.account.util.ccb.util;

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JaxbUtil {

	/**
	 * JavaBean转换成xml
	 * 
	 * @param obj
	 * @param encoding
	 * @return
	 */
	public static String convertToXml(Object obj, String encoding) {
		String result = null;
		try {
			JAXBContext context = JAXBContext.newInstance(obj.getClass());
			Marshaller marshaller = context.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);

			StringWriter writer = new StringWriter();
			marshaller.marshal(obj, writer);
			result = writer.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * xml转换成JavaBean
	 * 
	 * @param xml
	 * @param c
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T converyToJavaBean(String xml, Class<T> c) {
		T t = null;
		try {
			JAXBContext context = JAXBContext.newInstance(c);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			t = (T) unmarshaller.unmarshal(new StringReader(xml));
		} catch (Exception e) {
			e.printStackTrace();
		}

		return t;
	}
}

这样流程下来基本可以搞定xml和实体之间的互转,有更好的方法欢迎分享。

猜你喜欢

转载自blog.csdn.net/weixin_42140580/article/details/86142010