Cxf - 轉換器

襲冷發表於2014-04-19

一、說明

    對於一些比較複雜的組合型別資料,如如下介面中的getBookGroupByUser()方法:

import java.util.List;
import java.util.Map;

import javax.jws.WebService;

import com.xilen.cxf.entity.Book;
import com.xilen.cxf.entity.User;

@WebService
public interface UserInfoWs {

	public String sayHello(String name);

	public List<Book> getBookByUser(User u);

	public Map<String, Book> getUserRecommBook();

	public Map<User, List<Book>> getBookGroupByUser();

}

    Cxf框架可能因為無法自動解析而在釋出時丟擲異常:

Exception in thread "main" javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException
	at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:371)
	at org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:251)
	at org.apache.cxf.jaxws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl.java:155)
	at javax.xml.ws.Endpoint.publish(Unknown Source)
	at com.xilen.ServerMain.main(ServerMain.java:14)
Caused by: org.apache.cxf.service.factory.ServiceConstructionException
	at org.apache.cxf.jaxb.JAXBDataBinding.initialize(JAXBDataBinding.java:341)
	at org.apache.cxf.service.factory.AbstractServiceFactoryBean.initializeDataBindings(AbstractServiceFactoryBean...)
	at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean...)
	at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:704)
	at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean...)
	at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:265)
	at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:215)
	at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory...)
	at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:159)
	at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:211)
	at org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:456)
	at org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:334)
	... 4 more
Caused by: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
java.util.List is an interface, and JAXB can't handle interfaces.
	this problem is related to the following location:
		at java.util.List
		at private java.util.Map com.xilen.cxf.ws.jaxws_asm.GetBookGroupByUserResponse._return
		at com.xilen.cxf.ws.jaxws_asm.GetBookGroupByUserResponse

    附:兩個實體類

public class Book {
	private Integer id;
	private String name;
	private Date date;
	
	/*getter and setter */
 
}
public class User {
	private Integer id;
	private String name;
	private String email;
	
	/*getter and setter */

}
二、開發

    1、建立Java普通物件,對無法解析的資料型別重新封裝。如Map<User, List<Book>>型別的資料,可以做如下封裝

        (1)先將Map的一個鍵值對組成一個新的物件Item

public class Item {
	private User key;
	private List<Book> value;

	public Item() {
		super();
	}
	
	/* getter and setter */
	
}
        (2)將Item物件以集合型別做為最終轉換物件的屬性

public class DataSet {

	private List<Item> item = new ArrayList<Item>();

	public DataSet() {
		super();
	}
	
	/* getter and setter */
	
}

    2、開發Cxf轉換器。需要繼承javax.xml.bind.annotation.adapters.XmlAdapter<ValueType, BoundType>類。ValueType即自定義的資料型別,BoundType即受限制而需要被轉換的資料型別

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import com.xilen.cxf.entity.Book;
import com.xilen.cxf.entity.User;

public class MyXmlAdapter extends XmlAdapter<DataSet, Map<User, List<Book>>> {

	@Override
	public Map<User, List<Book>> unmarshal(DataSet v) throws Exception {

		Map<User, List<Book>> maps = new HashMap<User, List<Book>>();
		for (Item item : v.getItem()) {
			maps.put(item.getKey(), item.getValue());
		}
		return maps;
	}

	@Override
	public DataSet marshal(Map<User, List<Book>> v) throws Exception {
		
		DataSet ds = new DataSet();
		for (User user : v.keySet()) {
			Item item = new Item(user, v.get(user));
			ds.getItem().add(item);
		}
		return ds;
	}
	
}
   3、使用這個轉換器。使用時通過javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter這個註解修飾需要被轉換的介面方法上,並通過Value屬性指定轉換器

import java.util.List;
import java.util.Map;

import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import com.xilen.cxf.entity.Book;
import com.xilen.cxf.entity.User;
import com.xilen.cxf.ws.util.MyXmlAdapter;

@WebService
public interface UserInfoWs {

	public String sayHello(String name);

	public List<Book> getBookByUser(User u);

	public Map<String, Book> getUserRecommBook();

	public @XmlJavaTypeAdapter(MyXmlAdapter.class) Map<User, List<Book>> getBookGroupByUser();

}

三、附

    1、工程結構圖

        

    2、工程原始碼

        http://download.csdn.net/detail/u013379717/7210625 
 
 




相關文章