现在的位置: 首页 > 综合 > 正文

修改JAX-WS的序列化行为以及web service中传递Map对象

2013年03月12日 ⁄ 综合 ⁄ 共 3668字 ⁄ 字号 评论关闭

使用JAX-WS创建web service时,大部分对象都能通过JAXB序列化成xml,包括基本的java类型、普通的javabean、list,数组等。那么对于JAXB 不知道如何处理的一些类型需要编写一个适配器,该适配器继承javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>抽象类。

XmlAdapter类型参数:

BoundType - JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过ValueType 将此类型用作内存表示形式。
ValueType - JAXB 无需其他操作便知道如何处理的类型
XmlAdapter方法:
XmlAdapter.marshal(...):编组过程中,JAXB 绑定框架调用 XmlAdapter.marshal(..) 将 bound 类型修改为 value 类型,然后将 value 类型编组为 XML 表示形式。XmlAdapter.unmarshal(...):解组过程中,JAXB 绑定框架首先将 XML 表示形式解组为 value 类型,然后调用
XmlAdapter.unmarshal(..) 将 value 类型修改为 bound 类型。 

下面以Date对象说明如何自定义序列化的适配器

默认情况下,Java 绑定规则模式将Date 绑定到 XmlGregorianCalendar,现在我们将Date对象直接序列化成string的表示形式:

//实现适配器
public class DateXmlAdapter extends XmlAdapter<String, Date>
{
	@Override
	public String marshal(Date v) throws Exception
	{
		SimpleDateFormat fmt=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		return fmt.format(v);
	}

	@Override
	public Date unmarshal(String v) throws Exception
	{
		SimpleDateFormat fmt=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		return fmt.parse(v);
	}
}
@XmlAccessorType(XmlAccessType.FIELD)
public class UserInfo implements Serializable
{
	private int id;
	private String userName;
	//适配器注解
	@XmlJavaTypeAdapter(DateXmlAdapter.class)
	private Date birthday;
	
	public int getId()

	public void setId(int id)

	public String getUserName()

	public void setUserName(String userName)

	public Date getBirthday()

	public void setBirthday(Date birthday)

}

这样就完成了转换。这里要注意的是XmlJavaTypeAdapter是注解在元素上而不是方法上,如果形参是Date类型应该是setBirthday(@XmlJavaTypeAdapter(DateXmlAdapter.class) Date myDate)

  JAXB 中传递是不支持接口的,所以不能直接传递map对象,CXF默认是使用JAXB 序列化对象的所以也是不支持传递map对象的。
通常会有IllegalAnnotationException java.util.Map is an interface, and JAXB can't handle interfaces这样的异常提示。那么根据上面的原理,我们需要自定义一个适配器来解决这个问题。
首先定义一个web service接口,定义了两个方法一个是返回Map<String, UserInfo>,另一个接收Map<String, UserInfo>参数

@WebService
public interface IQueryUser
{
	@XmlJavaTypeAdapter(value=UserMapAdapter.class)
	Map<String, UserInfo> getUserMap();
	
	void setUserMap(@XmlJavaTypeAdapter(value=UserMapAdapter.class) @WebParam(name="userMap")Map<String, UserInfo> userMap);
}

这里需要模拟一个Map类:

@XmlType(name="UserMap")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserMap
{
	private List<UserEntry> entries = new ArrayList<UserEntry>();

	public List<UserEntry> getEntries()
	{
		return entries;
	}

	public void addEntry(UserEntry entry)
	{
		entries.add(entry);
	}

	public static class UserEntry
	{
		private String key;
		private UserInfo users;

		public UserEntry() {
		}

		public UserEntry(String key, UserInfo users) {
			this.key = key;
			this.users = users;
		}

		public UserEntry(Map.Entry<String, UserInfo> entry) {
			this.key = entry.getKey();
			this.users = entry.getValue();
		}

		public String getKey()
		{
			return key;
		}

		public void setKey(String key)
		{
			this.key = key;
		}

		public UserInfo getUsers()
		{
			return users;
		}

		public void setUsers(UserInfo users)
		{
			this.users = users;
		}

	}
}

实现适配器

public class UserMapAdapter extends XmlAdapter<UserMap, Map<String, UserInfo>>
{
	@Override
	public UserMap marshal(Map<String, UserInfo> v) throws Exception
	{
		UserMap uMap=new UserMap();
		for (Map.Entry<String, UserInfo> element : v.entrySet())
		{
			uMap.addEntry(new UserMap.UserEntry(element));
		}
		return uMap;
	}

	@Override
	public Map<String, UserInfo> unmarshal(UserMap v) throws Exception
	{
		List<UserMap.UserEntry> lstEntry=v.getEntries();
		Map<String, UserInfo> uMap=new HashMap<String,UserInfo>();
		for (UserMap.UserEntry userEntry : lstEntry)
		{
			uMap.put(userEntry.getKey(), userEntry.getUsers());
		}
		return uMap;
	}

}

使用工具生成客户端代理类后,客户端调用代码如下:

JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
soapFactoryBean.setAddress("http://localhost:8080/WebServiceDemo/queryuser");
soapFactoryBean.setServiceClass(IQueryUser.class);
IQueryUser queryService = (IQueryUser) soapFactoryBean.create();
		
UserMap uMapWrapper = queryService.getUserMap();//取得map
List<UserEntry> userList = uMapWrapper.getEntries();
for (UserEntry userEntry : userList)
{
	System.out.println(userEntry.key + "  " + userEntry.users.getUserName());
}
		
queryService.setUserMap(uMapWrapper);//传入map

抱歉!评论已关闭.