你带酒来,我有故事

Flex数据交互之WebService

:: 代码生涯 二十画生 1148℃ 0评论

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

  First rewrite webservice class as CYMService:

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:

<?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.

 

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即可。

 

  2013年12月13日修改

上面封装的CYMService类在工作中使用起来较麻烦,索性再封装以易用。

封装的类还叫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

 

 

转载请注明:二十画生 » Flex数据交互之WebService

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址