在進行編碼前有必要對一些基本的認識進行介紹,以便後面的講解。 java
一、JAXB: spring
JAXB可以使用Jackson對JAXB註解的支持實現(jackson-module-jaxb-annotations),既方便生成XML,也方便生成JSON,這樣一來能夠更好的標誌能夠轉換爲JSON對象的JAVA類。JAXB容許JAVA人員將JAVA類映射爲XML表示方式,經常使用的註解包括:@XmlRootElement,@XmlElement等等。 數據庫
JAXB(Java Architecture for XML Binding) 是一個業界的標準,是一項能夠根據XML Schema產生Java類的技術。該過程當中,JAXB也提供了將XML實例文檔反向生成Java對象樹的方法,並能將Java對象樹的內容從新寫到XML實例文檔。從另外一方面來說,JAXB提供了快速而簡便的方法將XML模式綁定到Java表示,從而使得Java開發者在Java應用程序中能方便地結合XML數據和處理函數。
apache
二、Java SE中的JAXB 數組
JAXB 2.0是JDK 1.6的組成部分。JAXB 2.2.3是JDK 1.7的組成部分。 app
2.1 JDK中JAXB相關的重要Class和Interface:
JAXBContext類,是應用的入口,用於管理XML/Java綁定信息。
Marshaller接口,將Java對象序列化爲XML數據。
Unmarshaller接口,將XML數據反序列化爲Java對象。 ide
2.2 JDK中JAXB相關的重要Annotation:
@XmlType,將Java類或枚舉類型映射到XML模式類型
@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或屬性的序列化。FIELD表示JAXB將自動綁定Java類中的每一個非靜態的(static)、非瞬態的(由@XmlTransient標註)字段到XML。其餘值還有XmlAccessType.PROPERTY和XmlAccessType.NONE。
@XmlAccessorOrder,控制JAXB 綁定類中屬性和字段的排序。
@XmlJavaTypeAdapter,使用定製的適配器(即擴展抽象類XmlAdapter並覆蓋marshal()和unmarshal()方法),以序列化Java類爲XML。
@XmlElementWrapper ,對於數組或集合(即包含多個元素的成員變量),生成一個包裝該數組或集合的XML元素(稱爲包裝器)。
@XmlRootElement,將Java類或枚舉類型映射到XML元素。
@XmlElement,將Java類的一個屬性映射到與屬性同名的一個XML元素。
@XmlAttribute,將Java類的一個屬性映射到與屬性同名的一個XML屬性。
函數
三、解組和編組 工具
解組:( unmarshalling )把數據從存儲媒介上轉化到內存中的過程,正好與編組相反。所以須要把 xml 文檔解組到 Java VM 中。這裏的複雜性不是在扁平數據中,由於這不是必需的,而在於從正確的數據到正確 Java 代碼變量的映射。若是映射是錯誤的,就不可能正確的訪問數據。固然,若是再嘗試從新編組還會形成更大的問題,而且問題傳播的很快。
編組:( marshalling )是把內存中的數據轉化到存儲媒介上的過程。所以在 java 和 XML 環境中,編組就是把一些 Java 對象轉換成一個或多個 XML 文檔。在數據庫環境中,則是把 Java 表示的數據存入數據庫。顯然,編組的祕密在於把 Java 實例中的面向對象結構轉化成適用於 XML 的扁平結構,或者 RDBMS 中的關係結構
ui
好的,下面開始編碼了。工程以上一篇的爲基礎。
1、建立Person類
其代碼爲:
package com.yao.spring.bean; import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID = -283567759187941425L; private String name; private int age; @Override public String toString() { return "Person [age=" + age + ", name=" + name + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }2、由於咱們其中要返回一個Map<String,Person>的類型,因此咱們要實現一個解組和編組的適配器工具。
2.1 建立Map轉換器類:MapConvertor,@XmlType註釋標明該類能夠轉化爲xml類型,@XmlAccessorType(XmlAccessType.FIELD) ,控制字段或屬性的序列化。
package com.yao.spring.util; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; @XmlType(name = "MapConvertor") @XmlAccessorType(XmlAccessType.FIELD) public class MapConvertor { private List<MapEntry> entries = new ArrayList<MapEntry>(); public void addEntry(MapEntry entry) { entries.add(entry); } public List<MapEntry> getEntries() { return entries; } public static class MapEntry { private String key; private Object value; public MapEntry() { super(); } public MapEntry(Map.Entry<String, Object> entry) { super(); this.key = entry.getKey(); this.value = entry.getValue(); } public MapEntry(String key, Object value) { super(); this.key = key; this.value = value; } public String getKey() { return key; } public void setKey(String key) { this.key = key; } public Object getValue() { return value; } public void setValue(Object value) { this.value = value; } } }2.2 建立Map適配器類 MapAdapter,用於編組與解組,重寫XmlAdapter的 編組(marshal )與解組(unmarshal)方法。
package com.yao.spring.util; import java.util.HashMap; import java.util.Map; import javax.xml.bind.annotation.adapters.XmlAdapter; /** * 對Map類型作轉換的類和適配器類 * @author Kangjun * */ public class MapAdapter extends XmlAdapter<MapConvertor, Map<String, Object>> { @Override public MapConvertor marshal(Map<String, Object> map) throws Exception { MapConvertor convertor = new MapConvertor(); for (Map.Entry<String, Object> entry : map.entrySet()) { MapConvertor.MapEntry e = new MapConvertor.MapEntry(entry); convertor.addEntry(e); } return convertor; } @Override public Map<String, Object> unmarshal(MapConvertor map) throws Exception { Map<String, Object> result = new HashMap<String, Object>(); for (MapConvertor.MapEntry e : map.getEntries()) { result.put(e.getKey(), e.getValue()); } return result; } }
這時的類結構以下:
3、建立要調用的接口:PersonService。注意到public Map<String, Person> getPersonMap()方法有註釋@XmlJavaTypeAdapter(MapAdapter.class),此處註釋的XmlJavaTypeAdapter是對自定義編組使用實現XmlAdapter的適配器,即MapAdapter這個類,該類實現了XmlAdapter適配器,所以要實現解組和編組兩個方法。可能有的初學讀者會提到:爲何咱們要實現編組和解組呢?緣由很簡單,CXF不能直接支持Map。
package com.yao.spring.service; import java.util.Map; import javax.jws.WebService; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import com.yao.spring.bean.Person; import com.yao.spring.util.MapAdapter; @WebService public interface PersonService { public Person getPerson(); @XmlJavaTypeAdapter(MapAdapter.class) public Map<String, Person> getPersonMap(); }
這時的類結構以下:
package com.yao.spring.service; import java.util.HashMap; import java.util.Map; import javax.jws.WebService; import com.yao.spring.bean.Person; @WebService(endpointInterface="com.yao.spring.service.PersonService") public class PersonServiceImpl implements PersonService { @Override public Person getPerson() { Person p = new Person(); p.setAge(22); p.setName("yaokj"); return p; } @Override public Map<String, Person> getPersonMap() { Person p = new Person(); p.setAge(25); p.setName("yaokj"); Map<String, Person> map = new HashMap<String, Person>(); map.put("yaokj", p); return map; } }5、修改cxf-servlet.xml文件,添加:<jaxws:endpoint id="personService" implementor="com.yao.spring.service.PersonServiceImpl" address="/PersonService"/>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:endpoint id="helloWorld" implementor="com.yao.spring.service.HelloWorldImpl" address="/HelloWorld"/> <jaxws:endpoint id="personService" implementor="com.yao.spring.service.PersonServiceImpl" address="/PersonService"/> </beans>6、修改client-beans.xml文件。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schema/jaxws.xsd"> <bean id="client" class="com.yao.spring.service.HelloWorld" factory-bean="clientFactory" factory-method="create"/> <bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.yao.spring.service.HelloWorld"/> <property name="address" value="http://localhost:8080/HelloSpringCXF/services/HelloWorld"/> </bean> <bean id="personClient" class="com.yao.spring.service.PersonService" factory-bean="personFactory" factory-method="create" /> <bean id="personFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> <property name="serviceClass" value="com.yao.spring.service.PersonService"/> <property name="address" value="http://localhost:8080/HelloSpringCXF/services/PersonService" /> </bean> </beans>7、編寫客戶端代碼:PersonClient
package com.yao.spring.client; import java.util.Map; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.yao.spring.bean.Person; import com.yao.spring.service.PersonService; public class PersonClient { public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"client-beans.xml"}); PersonService personService = (PersonService)ctx.getBean("personClient"); Person p = personService.getPerson(); System.out.println(p); Map<String,Person> map = personService.getPersonMap(); System.out.println("map: "+map.get("yaokj")); ctx.close(); System.exit(0); } }
這時的類結構以下:
9、運行PersonClient,並打印,成功。
2014-8-21 2:12:02 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@735cda3f: startup date [Thu Aug 21 02:12:02 CST 2014]; root of context hierarchy 2014-8-21 2:12:02 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [client-beans.xml] 2014-8-21 2:12:03 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@28e70e30: defining beans [client,clientFactory,personClient,personFactory]; root of factory hierarchy 2014-8-21 2:12:03 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass 信息: Creating Service {http://service.spring.yao.com/}HelloWorldService from class com.yao.spring.service.HelloWorld 2014-8-21 2:12:04 org.apache.cxf.wsdl.service.factory.ReflectionServiceFactoryBean buildServiceFromClass 信息: Creating Service {http://service.spring.yao.com/}PersonServiceService from class com.yao.spring.service.PersonService Person [age=22, name=yaokj] map: Person [age=25, name=yaokj] 2014-8-21 2:12:04 org.springframework.context.support.AbstractApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@735cda3f: startup date [Thu Aug 21 02:12:02 CST 2014]; root of context hierarchy 2014-8-21 2:12:04 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons 信息: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@28e70e30: defining beans [client,clientFactory,personClient,personFactory]; root of factory hierarchy