[Adobe开发者中心]构建Tour de Flex实况控制台的服务站点
这是来自Adobe开发者中心的一篇文章,原文地址是:
http://www.adobe.com/devnet/flex/articles/serverside_tourdeflex_dashboar...
RIAMeeting特将此文整理翻译后与读者分享:
Greg Wilson和Damien Mandrioli都在今天写了日志记录新的Tour de Flex 实况控制台(Tour de Flex real time dashboard)。Greg的灵感来自于“Tour de Flex”,并把他的想法在控制台中付诸实现。关于创建这个项目的经历,他在自己的博客上写了这段故事。Damien (来自于IBM/ILOG)在控制台的客户端编写上做出了极为出色的工作,包括在控制台上使用了非常酷的ILOG Elixir组件,并且他也分享了他的整个开发过程在他的博客上。
我在这个项目中的贡献就是底层实现部分的实时消息传递(real-time messaging)。下面我也将分享这个创建过程的详细信息。
首先预览一下工作流…

在这个工作流中,我们结合了PHP和Java的原因是有一段历史的。在Tour de Flex的最初版本中,还和Java没有任何关系:Greg坚持直接从他的PHP页面中载入示例的数据(示例ID和时间戳)。后来如图所示,我们增加了LiveCycle Data Service来支持控制台推送数据的需求,并且我们趁这个机会将一些代码(比如数据库持久性)从PHP中迁移到了Java。注意这里我们使用了LCDS来获取更好的性能以及高端通道的可测量性,但是这个应用也同样可以部署在BlazeDS上。
一个非常简单的结构就是客户端直接连接LCDS。比如,客户端可以请求一个远程对象,这样可以直接发送加载完毕的示例数据(示例ID和地理位置)到达消息的目的地。另一种方法就是,客户端可以使用一个Producer对象直接发布信息到目的地。因为一些逻辑(比如定位IP地址和持续数据)在传递信息到发起请求的客户端之前,已经被服务端执行了,如果你使用这个方法,就要写一个自定义的消息适配器。
我们可能在未来会使用一个或两个上述的方式简化工作流,下面的是目前正在使用的servlet的源代码(为了简洁起见,删除了日志和非必要的代码):
package com.adobe.tdf; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.maxmind.geoip.Location; import com.maxmind.geoip.LookupService; import flex.messaging.MessageBroker; import flex.messaging.messages.AsyncMessage; import flex.messaging.util.UUIDUtils; publicclass TDFServlet extends HttpServlet { // Unique clientID for the message service // The geocoding service protected LookupService lookupService; // A DAO to store sample requests in a database protected SampleRequestDAO dao = new SampleRequestDAO(); // The LCDS message broker protected MessageBroker messageBroker; // The LCDS messaging destination where real time sample requests information is pushed protected String destination; publicvoid init() throws ServletException { ServletConfig config = getServletConfig(); destination = config.getInitParameter("messaging.destination.name"); try { // Load the geocoding database in init() to make sure we load it only once lookupService = new LookupService(path, LookupService.GEOIP_MEMORY_CACHE); } catch (IOException e) { // We swallow the exception here. If the database is not available, the feed // will still work but won't provide the location info. } } protectedvoid doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (messageBroker == null) { messageBroker = MessageBroker.getMessageBroker(null); } SampleRequest sampleRequest = new SampleRequest(); try { sampleRequest.setSampleId(Integer.parseInt(request.getParameter("sampleId"))); } catch (Exception e) { thrownew RuntimeException(message); } // Geolocate the IP address and add the info to the message if (lookupService != null && ipAddress != null) { Location location = lookupService.getLocation(ipAddress); if (location != null) { sampleRequest.setLatitude(location.latitude); sampleRequest.setLongitude(location.longitude); sampleRequest.setCountry(location.countryCode); sampleRequest.setCity(location.city); } } try { dao.create(sampleRequest, ipAddress); } catch (RuntimeException e) { } if (subtopic == null) subtopic = "flex"; // Publish the message to specified destination and subtopic. AsyncMessage msg = new AsyncMessage(); msg.setDestination(destination); msg.setHeader("DSSubtopic", subtopic); msg.setClientId(clientID); msg.setMessageId(UUIDUtils.createUUID()); msg.setBody(sampleRequest); messageBroker.routeMessageToService(msg, null); PrintWriter out = response.getWriter(); out.println("<html><body>ok</body></html>"); } }
这个Servlet负责下面的工作:
1. 定位请求观看示例的客户端的IP地址。我们当前使用MaxMind Geolocation API。这个API使用起来非常简单,而且返回的数据看起来相当精确。
2. 保存已加载完毕的示例的信息到数据库。我们保持跟踪历史数据,来支持之后可能增加的数据可视化项目。
3. 发送加载完毕的示例的数据到一个消息的目的地。这个servlet使用了Message Service Java API来直接的推送信息到Flex终端(第97行到第104行)。注意类似的API也可以用在ColdFusion,所以CF开发者可以使用CF页面来代替这个servlet来推送信息到客户端。
通道
信息的目的地被设置为支持多种不同的通道:RTMP,长连接和正常连接。客户端的开发者可以自行决定采用哪种通道连接服务端。比如,如果你想使用RTMP作为主通道,在RTMP连接失败的时候转为长连接,在长连接失败的时候转为正常连接,你可以这样设置你的客户端的ChannelSet:
<mx:ChannelSet id="channelSet"><mx:RTMPChannel id="rtmp" url="rtmp://hostname:2037"/> <mx:AMFChannel url="http://hostname/context/messagebroker/amflongpolling"/> <mx:AMFChannel url="http://hostname/context/messagebroker/amfpolling"/> </mx:ChannelSet>
关于作者
Christophe Coenraets是Adobe的技术布道者,他专注于富因特网应用和企业集成。他从2003年Flex的初级产品开始就工作于Flex。在之前的Macromedia,他的工作职责是JRun,即企业级的J2EE应用服务。在加入Macromedia之前,Christophe在Sybase管理Java和互联网应用。Christophe在过去的15年里都是世界范围内的大会的知名演讲者。他的博客是http://coenraets.org。

.gif)
.gif)




.gif)
关于空指针异常
确认已经配置了BlazeDS环境,确认messaging-config.xml配置正确,否则创建不了messageBroker实例。
messageBroker.routeMessageToS
messageBroker.routeMessageToService(msg, null);的时候会出现空指针异常是什么原因引起的?
这flex文章翻译的不错
这flex文章翻译的不错,我会一直关注的,谢谢!
欢迎访问http://www.belle7.com
发表新评论