Flex數據交互之WebService

  In this article you will learn how to call webservices hosted on asp.net applications from flex.html

  First rewrite webservice class as CYMService:web

package Services
{
    import mx.controls.Alert;
    import mx.managers.CursorManager;
    import mx.rpc.AbstractOperation;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.soap.SOAPHeader;
    import mx.rpc.soap.WebService;
    
    public class CYMService extends WebService
    {
        private var _callBackHandler:Function; //成功時的回調函數
        private var _faultHandler:Function;    //失敗時的回調函數
        private var _args:Array;               //傳入的參數
        
        //構造函數 @wsdl:WebService地址
        public function CYMService(wsdl:String)
        {
            super();
            
            this.wsdl = wsdl;
            this.loadWSDL();
            
            CursorManager.setBusyCursor();
        }
        
        //設置成功時回調函數 @callBackHandler:回調函數
        public function set callBackHandler(callBackHandler:Function):void
        {
            CursorManager.removeBusyCursor();
            this._callBackHandler = callBackHandler;
        }
        
        //得到回調函數
        public function get callBackHandler():Function
        {
            
            return this._callBackHandler;
        }
        
        //設置傳入參數
        public function set args(args:Array):void
        {
            this._args = args;
        }
        
        //得到傳入參數
        public function get args():Array
        {
            return this._args;
        }
        
        //設置失敗時回調函數
        public function set faultHandler(faultHandler:Function):void
        {
            this._faultHandler = faultHandler;
        }
        
        //得到失敗時回調函數
        public function get faultHandler():Function
        {
            return this._faultHandler;
        }
        
        //設置SOAP頭
        public function initHeader(header:SOAPHeader):void
        {
            this.clearHeaders();
            this.addHeader(header);
        }
        
        //調用WebService中的函數 @functionName:要調用的函數 @args:傳入的參數
        public function sendOperation(functionName:String,args:Array):void
        {
            //根據方法名動態調用WebService服務器的方法
            var operation:AbstractOperation = this.getOperation(functionName);
            
            //爲調用的方法添加監聽器,回調函數由外部動態傳入
            operation.addEventListener(ResultEvent.RESULT,this.callBackHandler);
            
            //爲調用的方法添加錯誤監聽器,若是傳入的錯誤處理方法爲空,則調用默認的處理方法
            if(this.faultHandler != null)
            {
                operation.addEventListener(FaultEvent.FAULT,this.faultHandler); 
            }
            else
            {
                operation.addEventListener(FaultEvent.FAULT,defaultFaultHandler); 
            }
            //爲調用的方法傳參數,參數類型爲Array
            operation.arguments = args;
            
            //執行調用的方法
            operation.send();
        }
        
        //沒有設置失敗時回調函數時的默認回調函數
        private function defaultFaultHandler(event:FaultEvent):void
        {
            CursorManager.removeBusyCursor();
        }
    }
}

  Second, create class ServiceLocation to store webservice url:服務器

package Services
{
    public class ServiceLocation
    {
        //WebService地址
        public static var webServiceURL:String="http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl";
        
        public function ServiceLocation()
        {
        }
    }
}

  Third,call webservice's function,here is demo to call CYMService:app

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
               initialize="application1_initializeHandler(event)"
               applicationComplete="application1_applicationCompleteHandler(event)">
    <fx:Script>
        <![CDATA[
            import Services.CYMService;
            import Services.ServiceLocation;
            
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            
            private    var m_WebService:CYMService=null;
            protected function application1_initializeHandler(event:FlexEvent):void
            {
                // 初始WebService
                m_WebService=new CYMService(ServiceLocation.webServiceURL);
                m_WebService.callBackHandler = getResult;
                m_WebService.faultHandler = faultHandlerFun;
            }
            
            // 調用成功時,處理webservice結果
            private function getResult(event:ResultEvent):void
            {
                if(event.result != null)
                {
                    // doing something
                }
            }
            
            // 失敗時處理函數
            protected function faultHandlerFun(event:FaultEvent):void
            {
                Alert.show(event.toString());
            }
            
            
            protected function application1_applicationCompleteHandler(event:FlexEvent):void
            {
                // 加載杭州的天氣狀況
                var cityName:String = "杭州";
                var arr:Array = new Array();
                arr.push(cityName);
                
                // 調用webservice中的getWeatherbyCityName函數,arr爲參數列
                m_WebService.sendOperation("getWeatherbyCityName",arr);

            }
            
        ]]>
    </fx:Script>
   
</s:Application>

  Final, see the result of event.result that can be rendered on the screen and manipulated by you.asp.net

 

  source code is here.異步

 

  2013年11月25日 修改

  注意:Flex中WebService是異步的,因此不要期望在循環在調用WebService以得到不一樣的結果。函數

for(var i:int=0; i < MAX_CHILDREN; i++) 
{
     // 圖片
     var Simgid:String = AppData.GetValue(arr[i],"事件編號");
     getPicURL(Simgid);    
}
//經過圖片編號得到圖片地址
public function getPicURL(Simgid:String):void
{
    var styleName:String = "PicList"; //模型名字:圖片列表
    var arr:Array = new Array();
    arr.push(styleName);
    arr.push("Simgid='" + Simgid + "'");
                
    //調用webservice中的GetData函數,arr爲參數列
     m_WebService3.sendOperation("GetData",arr);
}

//調用成功時,處理webservice3結果(得到圖片地址)
private function getResult3(event:ResultEvent):void
{
  ......
}

 

  本想經過上面代碼得到每張圖片地址,但調試發現圖片地址均相同,且getResult3函數沒有調試進去(起碼沒有立刻調試進去),顯然是異步在做怪。測試

  解決上面問題有兩個:一是將異步以鎖的形式來達到同步效果,但查閱資料不推薦使用;二是圖片在一開始就所有查出放到Dictionary中,在循環中只需根據key查詢value便可。flex

 

  2013年12月13日修改

  上面封裝的CYMService類在工做中使用起來較麻煩,索性再封裝以易用。this

  封裝的類還叫CYMService,回調函數以參數形式傳入。

package Services
{
    /**
     * @author chenyuming
     */
    import mx.controls.Alert;
    import mx.managers.CursorManager;
    import mx.rpc.AbstractOperation;
    import mx.rpc.AsyncToken;
    import mx.rpc.IResponder;
    import mx.rpc.Responder;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.soap.SOAPHeader;
    import mx.rpc.soap.WebService;
    
    public class CYMService extends WebService
    {
        //構造函數 @wsdl:WebService地址
        public function CYMService(wsdl:String)
        {
            super();
            
            this.wsdl = wsdl;
            this.loadWSDL();
        }

        
        //調用WebService中的函數 
        public function call(methodName:String,callback:Function,...args):void
        {
            var method:AbstractOperation = this.getOperation(methodName);
            method.arguments = args;
            
            var call:AsyncToken = method.send();
            call.userDefinedCallback = callback;
            call.addResponder(new Responder(resultCallback, faultCallback));
        }
        
        //設置成功時回調函數
        public function resultCallback(event:ResultEvent):void 
        {
            var callback:Function = event.token.userDefinedCallback as Function;
            
            if (callback != null) 
            {
                var result:CYMServiceResult = new CYMServiceResult();
                result.error = false;
                result.result = event.result;
                callback(result);
            }
        }
        
        //設置失敗時回調函數
        public function faultCallback(event:FaultEvent):void 
        {
            var callback:Function = event.token.userDefinedCallback as Function;
            if (callback != null) 
            {
                var result:CYMServiceResult = new CYMServiceResult();
                result.error = true;
                result.errorMessage = event.fault.toString();
                callback(result);
            }
        }
    }
}

  其中CYMServiceResult定義以下:

package Services
{
    /**
     * @author chenyuming
     */
    public class CYMServiceResult
    {
        public function CYMServiceResult()
        {
            
        }
        
        public var error:Boolean = false;
        public var errorMessage:String = null;
        public var result:Object = null;
    }    
}

  使用起來就變得簡易了:

protected function btnGetData_clickHandler(event:MouseEvent):void
{
    // 加載城市的天氣狀況
    var cityName:String = StringUtil.trim(txtInput.text);
    var arr:Array = new Array();
    arr.push(cityName);
    
    var service:CYMService = new CYMService(ServiceLocation.webServiceURL);
    service.call("getWeatherbyCityName",getResult,arr);
}


private function getResult(event:CYMServiceResult):void
{
    if(event.error)  //調用錯誤
    {
        Alert.show(event.errorMessage);
    }
    else            //調用正確
    {
        txtOutput.text = "";
        var obj:Object= event.result;
        for each(var content:String in obj)
        {
            txtOutput.text += content + "\n";
        }
    }
}

  測試代碼:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
    
    <fx:Script>
        <![CDATA[
            import Services.CYMService;
            import Services.CYMServiceResult;
            import Services.ServiceLocation;
            
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.utils.StringUtil;

            private function getResult(event:CYMServiceResult):void
            {
                if(event.error)
                {
                    Alert.show(event.errorMessage);
                }
                else
                {
                    txtOutput.text = "";
                    var obj:Object= event.result;
                    for each(var content:String in obj)
                    {
                        txtOutput.text += content + "\n";
                    }
                }
            }
            
            protected function btnGetData_clickHandler(event:MouseEvent):void
            {
                // 加載城市的天氣狀況
                var cityName:String = StringUtil.trim(txtInput.text);
                var arr:Array = new Array();
                arr.push(cityName);
                
                var service:CYMService = new CYMService(ServiceLocation.webServiceURL);
                service.call("getWeatherbyCityName",getResult,arr);
            }
            
        ]]>
    </fx:Script>
    
    <s:TextArea id="txtOutput" x="28" y="69" width="917" height="498" fontFamily="宋體" fontSize="14"/>
    <s:TextInput id="txtInput" x="216" y="30" fontFamily="宋體" fontSize="14"/>
    <s:Button id="btnGetData" click="btnGetData_clickHandler(event)" x="374" y="30.5" label="獲取城市天氣數據" fontFamily="宋體" fontSize="14"/>
    <s:Label x="28" y="35" text="請輸出城市名稱,好比:杭州" fontFamily="宋體" fontSize="14"/>
    
</s:Application>

  運行結果:

  源碼下載在這

 

  相關文章

   (1)Flex數據交互之Remoting

相關文章
相關標籤/搜索