在CXF中用JAXB数据绑定支持HashMap类型

在CXF中用JAXB数据绑定支持HashMap类型
SOAP中不支持HashMap,但可以通过适配器将数组转换成HashMap的方式来支持。

这是通过JAXB2.0中一个适配器类来转换的,先看下这个类的说明:

 

javax.xml.bind.annotation.adapters
类 XmlAdapter<ValueType,BoundType>

java.lang.Object
  javax.xml.bind.annotation.adapters.XmlAdapter<ValueType,BoundType>

类型参数:
BoundType - JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过 ValueType 将此类型用作内存表示形式。
ValueType - JAXB 无需其他操作便知道如何处理的类型。

这样,我们先定义一个用来传送数据的通用数组,包含了KEY和VALUE两个成员用来存MAP的项:
public   class  OtherValues  {
    
public OtherValues () {};
    
    
public OtherValues (String key, String value) {
        
this.key = key;
        
this.value = value;
    }
;
    
    
public String key; 
    
    
public String value;
}


再定义一个转换类:(数组到HashMap的转换)
import  java.util.HashMap;
import  java.util.Map.Entry;
import  org.apache.log4j.Logger;

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

public   class  OtherValuesAdapter  extends  XmlAdapter < OtherValues[], HashMap < String,String >>   {
    
static Logger logger = Logger.getLogger (OtherValuesAdapter.class.getName());
    
  
public HashMap<String, String> unmarshal(OtherValues[] value ) {
      logger.error(
"unmarshal begin");
    HashMap
<String, String> r = new HashMap<String,String>();
    
for( OtherValues c : value )
      r.put(c.key, c.value);
    
return r;
  }

  
  
public OtherValues[] marshal( HashMap<String,String> value ) {
      logger.error(
"marshal begin");
      OtherValues[] pairs 
= new OtherValues[value.size ()];
    
int i = 0;
    
for(Entry<String,String> entry : value.entrySet()) {
        pairs[i
++= new OtherValues (entry.getKey(), entry.getValue());
    }

    
return pairs;
  }

}


我们需要在一个结构中来包含使用HashMap的变量,因为必须为这个变量再声明一个 @XmlJavaTypeAdapter,这样JAXB才会在收到相应消息时调用我们的转换类。这是结构定义:
import  java.util.HashMap;
import  javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public   class  MapValue  {
    
private String devName;
    
private String devIp;

    @XmlJavaTypeAdapter(OtherValuesAdapter.
class)
    
public HashMap <String, String> otherValues;
    
    
public String getDevIp() {
        
return devIp;
    }

    
public void setDevIp(String devIp) {
        
this.devIp = devIp;
    }

    
public String getDevName() {
        
return devName;
    }

    
public void setDevName(String devName) {
        
this.devName = devName;
    }


}


最后,在SOAP服务的声明中,使用这个结构:(注意是sendAlarmMap方法)
import  java.util.List;

import  javax.jws. * ;
import  javax.jws.soap. * ;
import  javax.jws.soap.SOAPBinding. * ;

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

@WebService
public   interface  NotifyService  {
    
public int sendAlarm (DeviceValue alarm);
    
    
public String sendAlarmString (String stralarm);
    
    
public List<DeviceValue> sendAlarmArr (List<DeviceValue> arr);

    
public int sendAlarmMap (MapValue m);
    
}



下面,我们来看如何通过JAVA及PERL的方式调用这个服务:
JAVA的方式:
         NotifyService s  =  (NotifyService) getBean ( " notifyClient " );

             MapValue mv 
=   new  MapValue ();
            mv.otherValues 
=   new  HashMap < String, String >  ();
            mv.otherValues.put (
" hehe2 " " a " );
            mv.otherValues.put (
" 2 " " b " );

            mv.setDevIp (
" he " );
            mv.setDevName (
" hehe2 " );
            
            
int  r  =  s.sendAlarmMap(mv);
            logger.info(
" recv:  "   +  r);


PERL的方式:
{ #  call send map alarm
     my   @params   =  (SOAP :: Data -> name(arg0 => {
        devName
=> " hehe " ,  
        devIp
=> " ip1 " ,
        otherValues
=> [{
            item 
=>  [
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe1 " ,  value => " ip1 " } ,  
               {key
=> " hehe2 " ,  value => " ip2 " }]
        }]
    }));
    
    
my   $method   =  SOAP :: Data -> name( ' sendAlarmMap ' );
    
    
my   $result   =   $soap -> call( $method   =>   @params );
    
    
print   " \nsend map alarm result:\n " ;
    
if  ( $result -> fault)
    {
       
print   $result -> faultstring;
    }
    
else
    {
       
print   $result -> result;
    }
    
print   " \n\n " ;
}


产生的SOAP消息如下:
请求:
<? xml version="1.0" encoding="UTF-8" ?> < soap:Envelope  xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"  xmlns:soapenc ="http://schemas.xmlsoap.org/soap/encoding/"  xmlns:xsd ="http://www.w3.org/2001/XMLSchema"  soap:encodingStyle ="http://schemas.xmlsoap.org/soap/encoding/"  xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/" >< soap:Body >< sendAlarmMap >< arg0 >< devName > hehe </ devName >< otherValues >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip1 </ value >< key > hehe1 </ key ></ item >< item >< value > ip2 </ value >< key > hehe2 </ key ></ item ></ otherValues >< devIp > ip1 </ devIp ></ arg0 ></ sendAlarmMap ></ soap:Body ></ soap:Envelope >


回应:
< soap:Envelope  xmlns:soap ="http://schemas.xmlsoap.org/soap/envelope/" >< soap:Body >< ns1:sendAlarmMapResponse  xmlns:ns1 ="http://magic.nms.exchangebit.com/" >< return > 99 </ return ></ ns1:sendAlarmMapResponse ></ soap:Body ></ soap:Envelope >


总结:
有了转换器这个工具,我们可以在SOAP的JAXB绑定里支持各种JAVA的COLLECTION类型,以及自定义类型,打破了SOAP原始支持类型的限制。



有兴趣可以访问下我的生活博客: qqmovie.qzone.com

你可能感兴趣的:(在CXF中用JAXB数据绑定支持HashMap类型)