1. 程式人生 > >XML學習筆記(六):Jaxb負責xml與javaBean對映

XML學習筆記(六):Jaxb負責xml與javaBean對映

前言:

1、兩套標準:Jax-ws(web service)和 Jax-rs(restful)。

2、在JAVA EE 5\6中,jaxb可以很方便的與jax-rs、jax-ws整合,極大的簡化了web service介面的開發工作量。jaxb負責xml與javaBean的對映。

3、cxf等架構的使用,ws中不需要手動寫對映,而restfu則需要手動書寫註解。(也可以使用JAXB的XJC工具,通過定義schema的方式實現Java物件與XML的繫結)。

4、jaxb除了在ws與restful中廣泛使用,也可以作為解析xml的一種日常技術。

一、web service中的jaxb

1、在使用cxf的客戶端時,一般使用 wsdl2java 命令生成,所以不需要自己寫jaxb的程式碼。如: 

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "cat", propOrder = {
    "color",
    "id",
    "name"
})
public class Cat {

    protected String color;
    protected Integer id;
    protected String name;
//......
}

2、其實這邊對映的就是 soap訊息,與訪問的 wsdl 具有一致性。

二、jaxb詳解。

(一)例項

1、javaBean例項:

package cn.rest.bean;

import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 
 * UserBean.java
 *
 * @title User的傳輸資料類
 * @description
 * @author SAM-SHO 
 * @Date 2014-11-25
 */

@XmlRootElement(name = "USER")
//@XmlAccessorType(XmlAccessType.FIELD ) //寫這個註解,就不需要@XmlElement註解,一般和XmlType一起使用,指定名稱。
//@XmlType(propOrder = { "name", "age" ,"userAddress","phoneList"})
public class UserBean {
	private String name;
	private String key;
	private String age;
	private UserAddress userAddress;//地址
	private List<UserPhone> phoneList ;//手機

	@XmlElement(name="NAME")
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@XmlElement(name = "AGE")
	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	@XmlElement(name = "UserAddress")
	public UserAddress getUserAddress() {
		return userAddress;
	}

	public void setUserAddress(UserAddress userAddress) {
		this.userAddress = userAddress;
	}

	@XmlElementWrapper(name = "PhoneList")//標註集合
	@XmlElement(name = "UserPhone")
	public List<UserPhone> getPhoneList() {
		return phoneList;
	}

	public void setPhoneList(List<UserPhone> phoneList) {
		this.phoneList = phoneList;
	}

	@XmlAttribute(name="key")//屬性
	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}
	
}
package cn.rest.bean;

public class UserPhone {
	
	private String type;//電話號碼型別
	private String num;//電話號碼
	
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	
}
package cn.rest.bean;

import javax.xml.bind.annotation.XmlElement;

public class UserAddress {
	
	private String homeAddress;//家庭地址
	private String workAddress;//公司地址
	
	@XmlElement(name = "HomeAddress")
	public String getHomeAddress() {
		return homeAddress;
	}
	public void setHomeAddress(String homeAddress) {
		this.homeAddress = homeAddress;
	}

	@XmlElement(name = "WorkAddress")
	public String getWorkAddress() {
		return workAddress;
	}
	public void setWorkAddress(String workAddress) {
		this.workAddress = workAddress;
	}

}

2、解析工具。

1)javaBean 對映成 xml,使用 Marshaller 。

	/**
	 * Objext 轉成 XML
	 * 
	 * @param object
	 */
	public static void Object2Xml(Object object) {
		// FileWriter writer = null;
		try {
			JAXBContext context = JAXBContext.newInstance(object.getClass());
			Marshaller marshal = context.createMarshaller();
			marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 格式化輸出
			marshal.setProperty(Marshaller.JAXB_ENCODING, "utf-8");// 編碼格式,預設為utf-8
			marshal.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xml頭資訊
			marshal.marshal(object, System.out);

			// writer = new FileWriter("shop.xml");
			// marshal.marshal(object, writer);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

2)xml 對映成 javaBean,使用 Unmarshaller 
	/**
	 * xml 轉成特定的Bean
	 * 
	 * @param xml
	 * @return
	 */
	public static UserBean parseXml2UserBean(String xml) {
		try {
			JAXBContext context = JAXBContext.newInstance(UserBean.class);
			InputSource is = new InputSource();
			StringReader xmlStr = new StringReader(xml);
			is.setCharacterStream(xmlStr);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			UserBean user = (UserBean) unmarshaller.unmarshal(is);
			return user;

		} catch (JAXBException e) {
			e.printStackTrace();
			return null;
		}
	}

3)測試:
		UserBean tUserBean = new UserBean();
		tUserBean.setName("SAM-SHO");
		tUserBean.setAge("27");
		tUserBean.setKey("屬性111");

		UserAddress tUserAddress = new UserAddress();
		tUserAddress.setWorkAddress("蘇州園區");
		tUserAddress.setHomeAddress("蘇州高新區");
		tUserBean.setUserAddress(tUserAddress);

		List<UserPhone> phoneList = new ArrayList<UserPhone>();
		UserPhone tUserPhone = new UserPhone();
		tUserPhone.setType("移動");
		tUserPhone.setNum("13612345678");
		phoneList.add(tUserPhone);

		tUserPhone = new UserPhone();
		tUserPhone.setType("聯通");
		tUserPhone.setNum("13798765432");
		phoneList.add(tUserPhone);
		tUserBean.setPhoneList(phoneList);

		ObjectAndXmlHandle.Object2Xml(tUserBean);

【輸出】
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<USER key="屬性111">
    <AGE>27</AGE>
    <NAME>SAM-SHO</NAME>
    <PhoneList>
        <UserPhone>
            <num>13612345678</num>
            <type>移動</type>
        </UserPhone>
        <UserPhone>
            <num>13798765432</num>
            <type>聯通</type>
        </UserPhone>
    </PhoneList>
    <UserAddress>
        <HomeAddress>蘇州高新區</HomeAddress>
        <WorkAddress>蘇州園區</WorkAddress>
    </UserAddress>
</USER>



(二)jaxb 註解詳解:

1、@XmlRootElement   將一個Java類對映為一段XML的根節點。引數:

name            定義這個根節點的名稱

namespace   定義這個根節點名稱空間

2、@XmlAccessorType  定義對映這個類中的何種型別需要對映到XML。可接收四個引數,分別是:

XmlAccessType.FIELD:對映這個類中的所有欄位到XML

XmlAccessType.PROPERTY:對映這個類中的屬性(get/set方法)到XML

XmlAccessType.PUBLIC_MEMBER:將這個類中的所有public的field或property同時對映到XML(預設)

XmlAccessType.NONE:不對映

3、@XmlElement  指定一個欄位或get/set方法對映到XML的節點。如,當一個類的XmlAccessorType 被標註為

PROPERTY時,在某一個沒有get/set方法的欄位上標註此註解,即可將該欄位對映到XML。引數:

defaultValue  指定節點預設值

         name             指定節點名稱

         namespace    指定節點名稱空間

         required         是否必須(預設為false)

         nillable           該欄位是否包含 nillable="true" 屬性(預設為false)

         type               定義該欄位或屬性的關聯型別

4、@XmlAttribute  指定一個欄位或get/set方法對映到XML的屬性。引數:

name             指定屬性名稱

         namespace    指定屬性名稱空間

         required         是否必須(預設為false)

5、@XmlTransient  定義某一欄位或屬性不需要被對映為XML。如,當一個類的XmlAccessorType 被標註為PROPERTY時,在某一get/set方法的欄位上標註此註解,那麼該屬性則不會被對映。

6、@XmlType 定義對映的一些相關規則。引數:

propOrder        指定對映XML時的節點順序

actoryClass     指定UnMarshal時生成對映類例項所需的工廠類,預設為這個類本身

factoryMethod  指定工廠類的工廠方法

name               定義XML Schema中type的名稱

namespace      指定Schema中的名稱空間

7、@XmlElementWrapper  為陣列元素或集合元素定義一個父節點。如,類中有一元素為List items,若不加此註解,該元素將被對映為

    <items>...</items>


    <items>...</items>

這種形式,此註解可將這個元素進行包裝,如:

    @XmlElementWrapper(name="items")
    @XmlElement(name="item")
    public List items;

將會生成這樣的XML樣式:

    <items>
        <item>...</item>
        <item>...</item>
    </items>

8、@XmlJavaTypeAdapter  自定義某一欄位或屬性對映到XML的介面卡。如,類中包含一個介面,我們可以定義一個介面卡(繼承自 javax.xml.bind.annotation.adapters.XmlAdapter類),指定這個介面如何對映到XML。

9、@XmlSchema 配置整個包的namespace,這個註解需放在package-info.java檔案中。