Flex + BlazeDS 学习笔记 (一) --- BlazeDS的功能原理及配置实例
BlazeDS Test Drive里面示例了主要的功能:
- HTTPService
- Web Services
- Remote-Object
- Messaging
其實現是基于一個叫flex.messaging.MessageBroker的Servlet。各種消息通道的配置都存在于WEB-INF/flex/services-config.xml及其包含的3個XML文件中。下面簡單介紹這四種不同的功能。
?
- HTTPService:
向服務器發送HTTP請求,典型用途是獲取服務器端的XML內容。服務器端可以采用任何技術:JSP、Servlet、ASP、PHP等,只要在請求的URL里面指定即可。這是個異步請求,服務器會返回result或fault事件,分別對應成功和失敗。可以把返回的結果直接綁定到DataGrid上。利用useProxy屬性和crossdomain.xml可以跨域訪問,這是解決沙箱效應的方法之一。
另一種方法就是不用HTTPService,而是寫一個JS或PHP腳本,用Ajax(XMLHTTP Object) 去訪問跨域URL。(跑題了)
示例:在proxy-config.xml配置HTTPService要請求的URL地址,在程序中用“destination”映射關系來訪問該URL,如示例中的“catalog”。將J返回的XML內容綁定到<mx:DataGrid>控件上。
main.mxml<mx:HTTPService id="srv" destination="catalog" useProxy="true"/><mx:DataGrid dataProvider="{srv.lastResult.catalog.product}" width="100%" height="100%"/> <mx:Button label="Get Data" click="srv.send()"/>?
WEB-INF/flex/proxy-config.xml<destination id="catalog"><properties><url>/{context.root}/testdrive-httpservice/catalog.jsp</url></properties></destination>
?- WebService?:
可以訪問基于SOAP的web服務,其返回的對象自動被反序列化為ActionScript對象。數據綁定、沙箱問 題等與HTTPService相同。
示例:在proxy-config.xml配置WebService要請求的wsdl地址,在程序中用“destination”映射關系來訪問該URL,如示例中的“ws-catalog”。將返回的對象綁定到<mx:DataGrid>控件上。
?
main.mxml<mx:WebService id="srv" destination="ws-catalog" useProxy="true" showBusyCursor="true"/><mx:DataGrid dataProvider="{srv.getProducts.lastResult}" width="100%" height="100%"><mx:columns><mx:DataGridColumn dataField="productId" headerText="Product Id"/><mx:DataGridColumn dataField="name" headerText="Name"/><mx:DataGridColumn dataField="price" headerText="Price"/></mx:columns></mx:DataGrid><mx:Button label="Get Data" click="srv.getProducts()"/>?
proxy-config.xml<destination id="ws-catalog"><properties><wsdl>http://livecycledata.org/services/ProductWS?wsdl</wsdl><soap>*</soap></properties><adapter ref="soap-proxy"/></destination>?
?
- Remote-Object:
讓用戶可以直接訪問服務器上的對象的方法,要被訪問的對象是一個JAVA類,和Servlet、JSP差不多,但是遠程請求的這部分被隱藏起來了。返回的JAVA對象被自動反序列化為Actionscript對象,如果不加以指定類型,就成為一個動態對象。遠程訪問也是異步的,result或fault事件,分別對應成功和失敗。
?
示例:在remoting-config.xml配置遠程對象的類名,在程序中用“destination”映射關系來訪問該類的示例,如示例中的“product”。將返回的java.util.ArrayList對象綁定到<mx:DataGrid>控件上。
?
main.mxml<mx:RemoteObject id="srv" destination="product"/><mx:DataGrid dataProvider="{srv.getProducts.lastResult}" width="100%" height="100%"/> <mx:Button label="Get Data" click="srv.getProducts()"/> ?
remoting-config.xml<destination id="product"><properties><source>flex.samples.product.ProductService</source></properties></destination>?
?
package flex.samples.product; import java.util.ArrayList; public class ProductService {public List getProducts() {List list = new ArrayList();list.add(new Product(100, "abc"));return list;} } public class Product implements Serializable {private int productId;private String name;public Product(int productId, String name) {...}public int getProductId() {return productId;}public void setProductId(int productId) {this.productId = productId;public String getName() {return name;}public void setName(String name) {this.name = name;} }?
?
- Messaging
消息本身包含消息頭和消息體,消息頭的格式是固定的,消息體的內容可以隨意寫。接觸過狀態機、分布式嵌入式系統編程的會很容易理解。
消息服務允許Flex客戶端可以發布(Publish)和訂閱(Subscribe)消息,相應的,客戶端的被稱為生產者(Producer)和消費者(Consumer),其實也就是發送和接受消息了。
當一個消息被發到已訂閱的目的地(destination)時,就會觸發一個客戶端的message事件。發布的任何消息會發給所有訂閱的人,即使是生產者自己。如果某一訂閱方只想收到特定的消息,可以在訂閱時使用selecor屬性來指定過濾條件,只有符合條件的消息才會被服務器轉發。如果想要服務器產生消息,可以產生一個flex.messaging.messages.AsyncMessage類的實例,用flex.messaging.MessageBroker發送出去。
?
示例:在服務器端發布消息。通過JSP或Servlet建立一個無限循環線程產生消息。在messaging-config.xml配置消息通道(channel),在程序中用“destination”映射關系來訪問該通道,如示例中的“feed”。
startfeed.jsp <%try {Feed feed = new Feed();feed.start();out.println("Feed Started");} catch (Exception e) {out.println("A problem occured while starting the feed: "+e.getMessage());} %>?
Feed.java import java.util.*; import flex.messaging.MessageBroker; import flex.messaging.messages.AsyncMessage; import flex.messaging.util.UUIDUtils; public class Feed {private static FeedThread thread;public Feed() {}public void start() {if (thread == null) {thread = new FeedThread();thread.start();}}public void stop() {thread.running = false;thread = null;}public static class FeedThread extends Thread {public boolean running = true;public void run() {MessageBroker msgBroker = MessageBroker.getMessageBroker(null);String clientID = UUIDUtils.createUUID();Random random = new Random();double initialValue = 35;double currentValue = 35;double maxChange = initialValue * 0.005;while (running) {double change = maxChange - random.nextDouble() * maxChange * 2;double newValue = currentValue + change;if (currentValue < initialValue + initialValue * 0.15&& currentValue > initialValue - initialValue * 0.15) {currentValue = newValue;} else {currentValue -= change;}AsyncMessage msg = new AsyncMessage();msg.setDestination("feed");msg.setClientId(clientID);msg.setMessageId(UUIDUtils.createUUID());msg.setTimestamp(System.currentTimeMillis());msg.setBody(new Double(currentValue));msgBroker.routeMessageToService(msg, null);System.out.println("" + currentValue);try {Thread.sleep(300);} catch (InterruptedException e) {}}}} }
?
WEB-INF/flex/messaging-config.xml<destination id="feed"><!-- Destination specific channel configuration can be defined if needed<channels><channel ref="my-streaming-amf"/></channels> --></destination> ?
?
示例:客戶端可以發布和訂閱消息,在messaging-config.xml配置消息目的地,在程序中用“destination”映射關系來訪問該類的示例,如示例中的“chat”。注意,通道及其端點(endpoint)真正的定義是在service-config.xml中,messaging-config.xml中僅僅是引用它們。
?
?
<mx:Producer id="producer" destination="chat"/><mx:Consumer id="consumer" destination="chat" message="messageHandler(event.message)" selector="prop1 = 10" /><mx:Script><!--[CDATA[import mx.messaging.messages.AsyncMessage;import mx.messaging.messages.IMessage;private function send():void{var message:IMessage = new AsyncMessage();message.headers = new Array(); message.headers["prop1"] = 10;message.body.chatMessage = msg.text;producer.send(message);msg.text = "";}private function messageHandler(message:IMessage):void{log.text += message.body.chatMessage + "/n"; }]]--></mx:Script>?
WEB-INF/flex/messaging-config.xml<destination id="chat"/>?
WEB-INF/flex/service-config.xml<channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel"><endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/></channel-definition>?
?
可以看到,messaging包括兩大類不同的消息通道。分別是streaming channel和polling channel,每一類又有一些擴展類型。
?
采用polling channel,可以配置為每隔一段時間就輪詢一次,也可以配置讓服務器在無數據時等待,直到有數據時才響應(長輪詢)。輪詢響應完成后后就結束連接。
?
采用streaming channel時,服務器的響應一直保持連接狀態,這樣服務器一次連接后,可以持續下發數據到客戶端。由于HTTP連接不是雙工的,所以一條AMF或HTTP通道實際上需要2條瀏覽器連接,分別用于上行和下行數據。這第二條連接僅在需要向服務器發送數據時才建立,之后立即釋放。這種通道特別適合實時性高、客戶端刷新的應用。比起輪詢,這種模式有效減少了反復建立連接的開銷。
?
?
IE和Firefox瀏覽器在每個session最大連接數上有些不同。如果因此導致streaming channel建立失敗,則BlazeDS會自動使用messaging-config.xml配置的下一個連接。
?
實例:定義多個默認通道,作為備份。
WEB-INF/flex/messaging-config.xml<default-channels><channel ref="my-streaming-amf"/><channel ref="my-polling-amf"/><channel ref="per-client-qos-polling-amf"/> </default-channels>?
?
如果不在XML中配置消息通道,也可以在Actionscript腳本中動態賦值。
<mx:Script><!--[CDATA[import mx.messaging.channels.StreamingAMFChannel;import mx.messaging.ChannelSet;import mx.messaging.channels.AMFChannel;import mx.messaging.events.MessageEvent;import mx.messaging.messages.AsyncMessage;import mx.messaging.messages.IMessage;private function initComp():void{var myStreamingAMF:AMFChannel = new StreamingAMFChannel("my-streaming-amf", "../messagebroker/streamingamf");var myPollingAMF:AMFChannel = new AMFChannel("my-polling-amf", "../messagebroker/amfpolling");myPollingAMF.pollingEnabled = true;myPollingAMF.pollingInterval = 2000;var channelSet:ChannelSet = new ChannelSet();channelSet.addChannel(myStreamingAMF);channelSet.addChannel(myPollingAMF);consumer.channelSet = channelSet; producer.channelSet = channelSet;}]]--></mx:Script> ?
總結
以上是生活随笔為你收集整理的Flex + BlazeDS 学习笔记 (一) --- BlazeDS的功能原理及配置实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中data是什么意思_pyt
- 下一篇: 智能不止联络,容联助力银行以服务创造价值