修改JAX-WS的序列化行为以及web service中传递Map对象
2013-12-09 17:15
435 查看
使用JAX-WS创建web service时,大部分对象都能通过JAXB序列化成xml,包括基本的java类型、普通的javabean、list,数组等。那么对于JAXB 不知道如何处理的一些类型需要编写一个适配器,该适配器继承javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>抽象类。
XmlAdapter类型参数:
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的表示形式:
这样就完成了转换。这里要注意的是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>参数
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
相关文章推荐
- 关于Intent传递对象以及序列化技巧
- JAX-WS:背后的技术JAXB及传递Map
- JAX-WS:背后的技术JAXB及传递Map
- Web Service中Axis与DotNet互操作最佳实践:传递java.util.Map对象给C#(译)
- MyEclipse8.5 基于jax-ws的webservice对象(实体)传递的开发
- Android中数据的传递以及对象序列化
- JAX-WS:背后的技术JAXB及传递Map
- Parcelable 序列化对象传递数据 以及传递集合demo
- Android中传递对象的三种方法以及Java对象的序列化和反序列化实践
- JAX-WS:背后的技术JAXB及传递Map
- JAX-WS和JAX-RPC方式调用Web Service的Java客户端
- Android的跨进程通信介绍----------------aidl,传递复杂对象以及Server和Clicent之间的回调
- JNI学习积累之三 ---- 操作JNI函数以及复杂对象传递
- servlet(三)-如何使用传参-三种转发方式、传递参数以及对象中数据的范围
- Java中对象、对象引用、堆、栈、值传递以及引用传递的详细解释
- Application对象的使用-数据传递以及内存泄漏.
- JSON对象中的JSONObject和JSONArray以及与Map、String、数组的转化
- 转载:java方式的将java对象以及list或者map转化为json数据 .
- android传递数据bundle封装传递map对象
- Android笔记 Application对象的使用-数据传递以及内存泄漏问题