隨筆-124  評論-194  文章-0  trackbacks-0
          SOAP中不支持HashMap,但可以通過適配器將數(shù)組轉(zhuǎn)換成HashMap的方式來支持。

          這是通過JAXB2.0中一個適配器類來轉(zhuǎn)換的,先看下這個類的說明:

           

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

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

          類型參數(shù):
          BoundType - JAXB 不知道如何處理的一些類型。編寫一個適配器,以便允許通過 ValueType 將此類型用作內(nèi)存表示形式。
          ValueType - JAXB 無需其他操作便知道如何處理的類型。


          這樣,我們先定義一個用來傳送數(shù)據(jù)的通用數(shù)組,包含了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;
          }


          再定義一個轉(zhuǎn)換類:(數(shù)組到HashMap的轉(zhuǎn)換)
          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;
            }

          }


          我們需要在一個結(jié)構(gòu)中來包含使用HashMap的變量,因為必須為這個變量再聲明一個@XmlJavaTypeAdapter,這樣JAXB才會在收到相應(yīng)消息時調(diào)用我們的轉(zhuǎn)換類。這是結(jié)構(gòu)定義:
          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服務(wù)的聲明中,使用這個結(jié)構(gòu):(注意是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的方式調(diào)用這個服務(wù):
          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";
          }


          產(chǎ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>


          回應(yīng):
          <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>


          總結(jié):
          有了轉(zhuǎn)換器這個工具,我們可以在SOAP的JAXB綁定里支持各種JAVA的COLLECTION類型,以及自定義類型,打破了SOAP原始支持類型的限制。
          posted on 2007-10-29 16:41 我愛佳娃 閱讀(7238) 評論(5)  編輯  收藏 所屬分類: web技術(shù)

          評論:
          # re: 在CXF中用JAXB數(shù)據(jù)綁定支持HashMap類型 2007-10-29 23:38 | dihin
          如果返回類型是一個Map類型的話 該怎么做?
          上次項目就遇到這個問題  回復(fù)  更多評論
            
          # re: 在CXF中用JAXB數(shù)據(jù)綁定支持HashMap類型 2007-10-30 10:14 | 我愛佳娃
          我做了實際實驗,返回值里用上面的方法也是可以的呀:
          結(jié)構(gòu)聲明和轉(zhuǎn)換類不變,增加服務(wù)方法:
          public MapValue sendAlarmRetMap () {
          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");

          logger.info("return map");

          return mv;
          }

          在測試代碼中,增加調(diào)用:
          {
          MapValue mv = s.sendAlarmRetMap();
          logger.info("recv: " + mv.getDevIp() + mv.otherValues.get ("hehe2"));
          //this.assertEquals(r.size(), 10);
          }

          可以看到轉(zhuǎn)換類同樣是起作用的。我估計你沒有把MAP放到一個結(jié)構(gòu)中,只有這樣聲明的轉(zhuǎn)換類才能起作用。  回復(fù)  更多評論
            
          # re: 在CXF中用JAXB數(shù)據(jù)綁定支持HashMap類型 2007-10-30 16:56 | dihin
          我把Map改為
          public class MyMap {
          private HashMap<String,String> map;
          //getter/setter...
          }
          沒用轉(zhuǎn)換類也可以直接調(diào)用
          wsdl類型為
          - <xs:complexType name="myMap">
          - <xs:sequence>
          - <xs:element name="map">
          - <xs:complexType>
          - <xs:sequence>
          - <xs:element maxOccurs="unbounded" minOccurs="0" name="entry">
          - <xs:complexType>
          - <xs:sequence>
          <xs:element minOccurs="0" name="key" type="xs:string" />
          <xs:element minOccurs="0" name="value" type="xs:string" />
          </xs:sequence>
          </xs:complexType>
          </xs:element>
          </xs:sequence>
          </xs:complexType>
          </xs:element>
          </xs:sequence>
          </xs:complexType>
            回復(fù)  更多評論
            
          # re: 在CXF中用JAXB數(shù)據(jù)綁定支持HashMap類型 2007-10-30 20:53 | 我愛佳娃
          @dihin
          我開始就是這樣的,什么也不做,WSDL文件生成可以,但到實際調(diào)用時不能成功。還原不了MAP。
          你是不是用的Aegis數(shù)據(jù)綁定?似乎這種可以直接支持,JAXB只能加XMLADAPTER。  回復(fù)  更多評論
            
          # re: 在CXF中用JAXB數(shù)據(jù)綁定支持HashMap類型 2012-07-18 18:44 | jerry.lees
          這樣轉(zhuǎn)換以后 傳中文會有亂碼問題,該怎么解決?。?nbsp; 回復(fù)  更多評論
            
          主站蜘蛛池模板: 卓尼县| 张北县| 宽甸| 嘉善县| 巴马| 安陆市| 新河县| 海安县| 进贤县| 靖江市| 长垣县| 洛阳市| 襄城县| 云和县| 来凤县| 永新县| 蒙城县| 株洲县| 平原县| 东宁县| 开封市| 通化市| 江山市| 页游| 加查县| 青神县| 镶黄旗| 乐清市| 石柱| 册亨县| 沁水县| 曲靖市| 鸡东县| 漳浦县| 县级市| 治多县| 精河县| 阿勒泰市| 唐山市| 香河县| 平罗县|