flex+blazeds+java後臺訊息推送(簡單示例)
現在有個問題需要大家思考一下,有個已經上線了的專案,有好好幾千甚至上萬的客戶在使用了。現在專案開發商想釋出一個通知。在今天下午6點需要重新啟動伺服器,想讓線上的人在在預定的時間內都收到訊息,讓大家做好相應的準備,大家會怎麼做?
1、逐個打電話
2、在前臺弄一個定時器,每隔一定的時間重新整理一次
3、後臺訊息主動往前臺推送
相信你已經做出選擇了。。。呵呵 ,下面講一個簡單的例子,
首先,新建一個web專案,新增開發flex需要的jar包,和blazeds相關檔案,然後把web專案轉成flex專案(不明白怎麼弄沒事,過幾天會寫一篇這樣的文章),然後修改一下services-config.xml和messaging-config.xml檔案,新增如下程式碼
services-config.xml
1. <channel-definition
2. id="my-streaming-amf"
3. class="mx.messaging.channels.StreamingAMFChannel">
4. <endpoint
5. url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf"
6. class="flex.messaging.endpoints.StreamingAMFEndpoint"
7. />
8. <properties>
9. <idle-timeout-minutes>0</idle-timeout-minutes>
10. <max-streaming-clients>10</max-streaming-clients>
11. <server-to-client-heartbeat-millis>5000
12. </server-to-client-heartbeat-millis>
13. <user-agent-settings>
14. <user-agent
15. match-on="MSIE"
16. kickstart-bytes="2048"
17. max-streaming-connections-per-session="1"
18. />
19. <user-agent match-on="Firefox"
20. kickstart-bytes="2048"
21. max-streaming-connections-per-session="1"
22. />
23. </user-agent-settings>
24. </properties>
25. </channel-definition>
複製程式碼
messaging-config.xml
1. <destination
2. id="tick-data-feed">
3. <properties>
4. <server>
5. <allow-subtopics>true</allow-subtopics>
6. <subtopic-separator>.</subtopic-separator>
7. </server>
8. </properties>
9. <channels>
10. <channel
11. ref="my-polling-amf" />
12. <channelref="my-streaming-amf"
13. />
14. </channels>
15. </destination>
複製程式碼
OK,完了之後,我們新建一個servlet作為服務端
1. package com.serverpush;
2.
3. import java.io.IOException;
4. import
5. javax.servlet.ServletException;
6. import
7. javax.servlet.http.HttpServlet;
8. import
9. javax.servlet.http.HttpServletRequest;
10. import
11. javax.servlet.http.HttpServletResponse;
12.
13. import
14. com.model.Tick;
15.
16. import flex.messaging.MessageBroker;
17. import
18. flex.messaging.messages.AsyncMessage;
19. import
20. flex.messaging.util.UUIDUtils;
21.
22. /**
23. * Servlet implementation class
24. TickCacheServlet
25. */
26. public class TickCacheServlet extendsHttpServlet
27. {
28. private static final long serialVersionUID= 1L;
29. private static
30. FeedThread thread;
31.
32. /**
33. * @see
34. HttpServlet#HttpServlet()
35. */
36. public TickCacheServlet() {
37. super();
38. //
39. TODO Auto-generated constructor stub
40. }
41.
42. /**
43. * @see
44. HttpServlet#doGet(HttpServletRequestrequest, HttpServletResponse
45. *
46. response)
47. */
48. protected void doGet(HttpServletRequest
49. request,
50. HttpServletResponse response) throwsServletException, IOException
51. {
52. //接收前臺引數
53. String cmd =request.getParameter("cmd");
54. if
55. (cmd.equals("start")) {
56. start();
57. }
58. if (cmd.equals("stop"))
59. {
60. stop();
61. }
62. }
63.
64. public void start() {
65. if (thread == null)
66. {
67. thread = new
68. FeedThread();
69. thread.start();
70. }
71. System.out.println("start!!");
72. }
73.
74. public
75. void stop() {
76. thread.running = false;
77. thread = null;
78. }
79.
80. /**
81. *
82. @see HttpServlet#doPost(HttpServletRequestrequest, HttpServletResponse
83. *
84. response)
85. */
86. protected void doPost(HttpServletRequest
87. request,
88. HttpServletResponse response) throwsServletException, IOException
89. {
90. doGet(request, response);
91. }
92. //執行緒類,每隔多長時間傳送一次
93. public static class
94. FeedThread extends Thread {
95. public boolean running = true;
96. public void
97. run() {
98. MessageBroker msgBroker =
99. MessageBroker.getMessageBroker(null);
100. String clientID =
101. UUIDUtils.createUUID();
102. int i = 0;
103. while (running) {
104. Tick tick = new
105. Tick();
106. tick.setMessageCN("今天下午6點更新程式需重啟伺服器");
107. tick.setSeqNo(String.valueOf(i));
108. System.out.println(i);
109.
110. AsyncMessage
111. msg = new
112. AsyncMessage();
113. msg.setDestination("tick-data-feed");
114. msg.setHeader("DSSubtopic",
115. "tick");
116. msg.setClientId(clientID);
117. msg.setMessageId(UUIDUtils.createUUID());
118. msg.setTimestamp(System.currentTimeMillis());
119. msg.setBody(tick);
120. msgBroker.routeMessageToService(msg,
121. null);
122. i++;
123. try {
124. Thread.sleep(2000);
125. } catch (InterruptedException
126. e) {
127. }
128. }
129. }
130. }
131. }
複製程式碼
在新建一個model用來儲存訊息
1. package com.model;
2.
3. public class Tick {
4. private String
5. seqNo;
6. private String messageCN;
7.
8. public String getMessageCN()
9. {
10. return messageCN;
11. }
12.
13. public void setMessageCN(String messageCN)
14. {
15. this.messageCN = messageCN;
16. }
17.
18. public String getSeqNo()
19. {
20. return seqNo;
21. }
22.
23. public void setSeqNo(String seqNo)
24. {
25. this.seqNo = seqNo;
26. }
27. }
複製程式碼
後臺就搞定了。下面看前臺
新建一個mxml檔案和一個VO檔案
mxml:
1. <?xml version="1.0"
2. encoding="utf-8"?>
3. <s:Application
4. xmlns:fx="http://ns.adobe.com/mxml/2009"
5. xmlns:s="library://ns.adobe.com/flex/spark"
6. xmlns:mx="library://ns.adobe.com/flex/mx"
7. minWidth="955"
8. minHeight="600">
9. <s:layout>
10. <s:BasicLayout/>
11. </s:layout>
12.
13. <fx:Script>
14. <![CDATA[
15. import
16. mx.controls.Alert;
17. import mx.messaging.ChannelSet;
18. import
19. mx.messaging.Consumer;
20. import
21. mx.messaging.events.MessageEvent;
22.
23. protected function
24. submsg():void
25. {
26. Alert.show("click start");
27. var consumer:Consumer = new
28. Consumer();
29. consumer.destination ="tick-data-feed";
30. consumer.subtopic =
31. "tick";
32. consumer.channelSet = new
33. ChannelSet(["my-streaming-amf"]);
34. //新增message的監聽,當後臺有訊息傳送時,呼叫messageHandler
35.
36. consumer.addEventListener(MessageEvent.MESSAGE,messageHandler);
37.
38. consumer.subscribe();
39. }
40. private function
41. messageHandler(event:MessageEvent):void
42. {
43. var tick:TickVO =
44. event.message.body as TickVO;
45. txtTick.text = tick.messageCN+tick.seqNo;
46.
47. }
48.
49.
50. ]]>
51. </fx:Script>
52.
53. <fx:Declarations>
54. <!--
55. 將非可視元素(例如服務、值物件)放在此處 -->
56. </fx:Declarations>
57. <mx:Panel
58. x="32"
59. y="43"
60. width="362"
61. height="302"
62. layout="absolute"
63. title="Watch
64. Tick">
65. <mx:Label
66. x="72"
67. y="43"
68. text="Label"
69. id="txtTick"/>
70. <mx:Button
71. x="132"
72. y="71"
73. label="Button"
74. click="submsg()"/>
75. </mx:Panel>
76. </s:Application>
複製程式碼
VO,就是對應後臺的model
1. package
2. {
3. //遠端到後臺的Tick,也就是說他們倆現在是對應的關係了,你在後臺給model賦值了,在前臺flex中就可以通過VO
4. //取得model中的值
5. [RemoteClass(alias="com.model.Tick")]
6.
7. [Bindable]
8. public class TickVO
9. {
10. private var
11. _seqNo:String;
12. private var _messageCN:String;
13.
14. public function
15. TickVO()
16. {
17.
18. }
19. public function get seqNo():String
20. {
21. return
22. _seqNo;
23. }
24.
25. public function setseqNo(value:String):void
26. {
27. _seqNo
28. = value;
29. }
30.
31. public function get messageCN():String
32. {
33. return
34. _messageCN;
35. }
36.
37. public function set
38. messageCN(value:String):void
39. {
40. _messageCN =
41. value;
42. }
43.
44.
45. }
46. }
複製程式碼