FineReport設計器有自動的消息推送功能,可設定報表定時推送和正常的日報周報推送。官方有自己的消息推送的接口,不過有些使用者旺旺希望自己開發,符合自己需求的推送界面。
下面這個方案就從邏輯層面簡單闡述一個通訊類應該怎麼實作。
廢話不多說直接上代碼,為了保證新手能夠看懂,這個代碼基本上隻需要了解JS和JQ的正常寫法就行。
<code>;</code>
<code>(</code><code>function</code><code>($){</code>
<code> </code><code>/*定義一個工具對象,所有的工具以後都放進去*/</code>
<code> </code><code>HG = {};</code>
<code> </code><code>/*定義我們第一個基礎類OBJ*/</code>
<code> </code><code>HG.OBJ = </code><code>function</code><code>(options){</code>
<code> </code><code>//保證子類能夠繼承父類的預設成員變量</code>
<code> </code><code>this</code><code>.options = $.extend(</code><code>this</code><code>._defaultOptions(), options);</code>
<code> </code><code>//初始化對象</code>
<code> </code><code>this</code><code>._init();</code>
<code> </code><code>};</code>
<code> </code><code>$.extend(HG.OBJ.prototype, {</code>
<code> </code><code>_defaultOptions: </code><code>function</code> <code>() {</code>
<code> </code><code>return</code> <code>{classType:</code><code>"OBJ"</code><code>};</code>
<code> </code><code>},</code>
<code> </code><code>_init:</code><code>function</code><code>(){}</code>
<code> </code><code>});</code>
<code> </code><code>/*定義用于生成子類的方法*/</code>
<code> </code><code>HG.extend=</code><code>function</code><code>(parent,options){</code>
<code> </code><code>var</code> <code>son = $.extend(parent,{});</code>
<code> </code><code>son.prototype = $.extend(parent.prototype,options);</code>
<code> </code><code>return</code> <code>son;</code>
<code> </code><code>/*第一個就是要建構我們的通訊對象*/</code>
<code> </code><code>/****定義一些通訊用的私有成員和方法*****/</code>
<code> </code><code>//發送通道的狀态,為了減輕伺服器壓力,采取單通道發送</code>
<code> </code><code>var</code> <code>status = </code><code>true</code><code>;</code>
<code> </code><code>var</code> <code>sendMsgList = [];</code>
<code> </code><code>var</code> <code>receiveMsgList = [];</code>
<code> </code><code>var</code> <code>server = </code><code>null</code><code>;</code>
<code> </code><code>var</code> <code>sendType = </code><code>null</code><code>;</code>
<code> </code><code>var</code> <code>dataType = </code><code>null</code><code>;</code>
<code> </code><code>//最終發送消息的方法</code>
<code> </code><code>var</code> <code>send=</code><code>function</code><code>(msg,onReceive,onComplete,onFailed){</code>
<code> </code><code>if</code><code>(!msg.inList){</code>
<code> </code><code>msg.inList = </code><code>true</code><code>;</code>
<code> </code><code>sendMsgList.push(msg);</code>
<code> </code><code>}</code>
<code> </code><code>if</code><code>(status){</code>
<code> </code><code>status = </code><code>false</code><code>;</code>
<code> </code><code>var</code> <code>tempSendMsgList = sendMsgList;</code>
<code> </code><code>sendMsgList = [];</code>
<code> </code><code>FR.ajax({ </code>
<code> </code><code>url: server, </code>
<code> </code><code>type: sendType,</code>
<code> </code><code>dataType:dataType,</code>
<code> </code><code>data:{msgList:tempSendMsgList},</code>
<code> </code><code>success : </code><code>function</code><code>(receiveMsgList){</code>
<code> </code><code>status = </code><code>true</code><code>;</code>
<code> </code><code>onReceive(receiveMsgList);</code>
<code> </code><code>},</code>
<code> </code><code>complete: </code><code>function</code><code>(XMLHttpRequest,textStatus){</code>
<code> </code><code>onComplete(XMLHttpRequest,textStatus);</code>
<code> </code><code>error: </code><code>function</code><code>(XMLHttpRequest, textStatus, errorThrown){</code>
<code> </code><code>onFailed(XMLHttpRequest, textStatus, errorThrown);</code>
<code> </code><code>}</code>
<code> </code><code>});</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>setTimeout(</code><code>function</code><code>(){</code>
<code> </code><code>send(msg,onReceive,onComplete,onFailed);</code>
<code> </code><code>},1000);</code>
<code> </code><code>var</code> <code>formatDate = </code><code>function</code><code>(date){</code>
<code> </code><code>var</code> <code>d = </code><code>new</code> <code>Date(date);</code>
<code> </code><code>return</code> <code>d.getFullYear()+</code><code>"-"</code><code>+d.getMonth()+</code><code>"-"</code><code>+d.getDate()+</code><code>" "</code><code>+d.getHours()+</code><code>":"</code><code>+d.getMinutes()+</code><code>":"</code><code>+d.getSeconds();</code>
<code> </code><code>//通訊類,可以自己重寫onReceive的方法來實作自己的消息工具,消息的内容為JSON格式,自己定義就好了</code>
<code> </code><code>HG.CommunicationClient = HG.extend(HG.OBJ,{</code>
<code> </code><code>return</code> <code>{</code>
<code> </code><code>classType:</code><code>"CommunicationClient"</code><code>,</code>
<code> </code><code>//預設隻跟目前的伺服器進行聯絡</code>
<code> </code><code>server:FR.servletURL+</code><code>"?op=msgserver"</code><code>,</code>
<code> </code><code>sendType:</code><code>"POST"</code><code>,</code>
<code> </code><code>dataType:</code><code>"JSON"</code><code>,</code>
<code> </code><code>//輪詢的頻率,預設3秒1次,越快伺服器和用戶端壓力越大</code>
<code> </code><code>pollingRate:3000</code>
<code> </code><code>};</code>
<code> </code><code>_init:</code><code>function</code><code>(){</code>
<code> </code><code>server = </code><code>this</code><code>.options.server;</code>
<code> </code><code>sendType = </code><code>this</code><code>.options.sendType;</code>
<code> </code><code>dataType = </code><code>this</code><code>.options.dataType;</code>
<code> </code><code>this</code><code>.polling4Receive();</code>
<code> </code><code>send:</code><code>function</code><code>(msg){</code>
<code> </code><code>var</code> <code>self = </code><code>this</code><code>;</code>
<code> </code><code>send(msg,self.onReceive, self.onComplete, self.onFailed);</code>
<code> </code><code>//給某個使用者發文本消息</code>
<code> </code><code>sendText:</code><code>function</code><code>(toUserId,text){</code>
<code> </code><code>this</code><code>.send({action:</code><code>"send"</code><code>,userId:toUserId,time:</code><code>new</code> <code>Date().getTime(),content:{text:text}})</code>
<code> </code><code>onReceive:</code><code>function</code><code>(msg){</code>
<code> </code><code>if</code><code>(msg.length>0){</code>
<code> </code><code>for</code><code>( </code><code>var</code> <code>i=0; i<msg.length; i++ ){</code>
<code> </code><code>console.info(formatDate(msg[i].time)+</code><code>" "</code><code>+msg[i].name+</code><code>" "</code><code>+decodeURI(</code><code>"%E8%AF%B4%EF%BC%9A"</code><code>)+</code><code>" "</code><code>+msg[i].content.text);</code>
<code> </code><code>}</code>
<code> </code><code>onFailed:</code><code>function</code><code>(XMLHttpRequest, textStatus, errorThrown){</code>
<code> </code><code>onComplete:</code><code>function</code><code>(XMLHttpRequest, textStatus){</code>
<code> </code><code>/*向伺服器輪詢,檢查是否有自己的消息*/</code>
<code> </code><code>polling4Receive:</code><code>function</code><code>(){</code>
<code> </code><code>self.send({action:</code><code>"findMessage"</code><code>,inList:</code><code>false</code><code>});</code>
<code> </code><code>self.polling4Receive();</code>
<code> </code><code>},self.options.pollingRate);</code>
<code> </code><code>//先生成一個對話工具</code>
<code> </code><code>HG.Talk = </code><code>new</code> <code>HG.CommunicationClient();</code>
<code>})(jQuery);</code>
在任意一個你需要的系統或者界面引入這段JS,
然後最基本的文本消息發送
HG.Talk.sendText(接收者的使用者名,文本消息的内容);
當然,我們實際需求中需要的遠遠不止是發個文本這麼簡單,對于任意消息的發送該怎麼搞呢?
有兩種方法:
繼承HG.CommunicationClient實作新的自己的通訊類,或者重寫 HG.Talk的方法,兩種方式都是修改onReceive方法,上面的代碼中是把消息直接顯示到控制台當中的。
你可以根據你自己的需要發送任意JSON格式的msg并在onReceive中去實作你想要的展現方法。當然如果你想真正的了解它是怎麼運作的,可以花5分鐘看一遍代碼就清楚了
下面看看背景,因為暫時隻說邏輯,是以很多東西都不考慮,背景就會非常的簡單,隻需要有點JAVA基礎,并且了解FineReport的service接口就應該能看懂.
<code>package</code> <code>com.hg.plugin.plate.msgutils;</code>
<code> </code>
<code>import</code> <code>java.io.PrintWriter;</code>
<code>import</code> <code>java.util.ArrayList;</code>
<code>import</code> <code>java.util.Date;</code>
<code>import</code> <code>java.util.HashMap;</code>
<code>import</code> <code>java.util.List;</code>
<code>import</code> <code>java.util.Map;</code>
<code>import</code> <code>javax.servlet.http.HttpServletRequest;</code>
<code>import</code> <code>javax.servlet.http.HttpServletResponse;</code>
<code>import</code> <code>com.fr.fs.control.UserControl;</code>
<code>import</code> <code>com.fr.fs.web.service.ServiceUtils;</code>
<code>import</code> <code>com.fr.json.JSONArray;</code>
<code>import</code> <code>com.fr.json.JSONObject;</code>
<code>import</code> <code>com.fr.stable.fun.Service;</code>
<code>import</code> <code>com.fr.web.utils.WebUtils;</code>
<code>public</code> <code>class</code> <code>MessageServer </code><code>implements</code> <code>Service {</code>
<code> </code>
<code> </code><code>class</code> <code>Message{</code>
<code> </code><code>private</code> <code>long</code> <code>time = -</code><code>1</code><code>;</code>
<code> </code><code>private</code> <code>String fuserId = </code><code>""</code><code>;</code>
<code> </code><code>private</code> <code>String tuserId = </code><code>""</code><code>;</code>
<code> </code><code>private</code> <code>JSONObject content = JSONObject.create();</code>
<code> </code>
<code> </code><code>public</code> <code>Message(String fromUserId,String toUserId,JSONObject content){</code>
<code> </code><code>this</code><code>.fuserId = fromUserId;</code>
<code> </code><code>this</code><code>.tuserId = toUserId;</code>
<code> </code><code>this</code><code>.content = content;</code>
<code> </code><code>time = </code><code>new</code> <code>Date().getTime();</code>
<code> </code><code>public</code> <code>JSONObject toJSON() </code><code>throws</code> <code>Exception{</code>
<code> </code><code>JSONObject jo = JSONObject.create();</code>
<code> </code><code>jo.put(</code><code>"userId"</code><code>, fuserId);</code>
<code> </code><code>jo.put(</code><code>"name"</code><code>, UserControl.getInstance().getByUserName(fuserId).getRealname());</code>
<code> </code><code>jo.put(</code><code>"content"</code><code>, content);</code>
<code> </code><code>jo.put(</code><code>"time"</code><code>, time);</code>
<code> </code><code>return</code> <code>jo;</code>
<code> </code><code>}</code>
<code> </code><code>private</code> <code>static</code> <code>Map<String,List<Message>> messageStore = </code><code>new</code> <code>HashMap<String,List<Message>>();</code>
<code> </code><code>@Override</code>
<code> </code><code>public</code> <code>String actionOP() {</code>
<code> </code><code>return</code> <code>"msgserver"</code><code>;</code>
<code> </code><code>public</code> <code>void</code> <code>process(HttpServletRequest req, HttpServletResponse res,String op, String sessionID) </code><code>throws</code> <code>Exception {</code>
<code> </code><code>String msgListStr = WebUtils.getHTTPRequestParameter(req, </code><code>"msgList"</code><code>);</code>
<code> </code><code>JSONArray msgListJa = </code><code>new</code> <code>JSONArray(msgListStr);</code>
<code> </code><code>List<JSONObject> msgList = sortMessageList(msgListJa);</code>
<code> </code><code>String fromUserId = ServiceUtils.getCurrentUserName(req);</code>
<code> </code><code>//投遞給别人的信件</code>
<code> </code><code>for</code><code>(JSONObject msg : msgList){</code>
<code> </code><code>String tuserId = msg.getString(</code><code>"userId"</code><code>);</code>
<code> </code><code>if</code><code>(!messageStore.containsKey(tuserId)){</code>
<code> </code><code>messageStore.put(tuserId, </code><code>new</code> <code>ArrayList<Message>());</code>
<code> </code><code>messageStore.get(tuserId).add(</code><code>new</code> <code>Message(fromUserId,tuserId,msg.getJSONObject(</code><code>"content"</code><code>)));</code>
<code> </code><code>//檢視是否有自己的信件</code>
<code> </code><code>if</code><code>(!messageStore.containsKey(fromUserId)){</code>
<code> </code><code>messageStore.put(fromUserId, </code><code>new</code> <code>ArrayList<Message>());</code>
<code> </code><code>List<Message> sendList = messageStore.get(fromUserId);</code>
<code> </code><code>JSONArray result = JSONArray.create();</code>
<code> </code><code>for</code><code>(Message msg : sendList){</code>
<code> </code><code>result.put(msg.toJSON());</code>
<code> </code><code>messageStore.put(fromUserId, </code><code>new</code> <code>ArrayList<Message>());</code>
<code> </code><code>res.setContentType(</code><code>"text/html;charset=UTF-8"</code><code>);</code>
<code> </code><code>res.setCharacterEncoding(</code><code>"UTF-8"</code><code>);</code>
<code> </code><code>PrintWriter write = res.getWriter();</code>
<code> </code><code>write.write(result.toString());</code>
<code> </code><code>write.flush();</code>
<code> </code><code>write.close();</code>
<code> </code><code>private</code> <code>static</code> <code>List<JSONObject> sortMessageList(JSONArray msgListJa) </code><code>throws</code> <code>Exception{</code>
<code> </code><code>List<JSONObject> result = </code><code>new</code> <code>ArrayList<JSONObject>();</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>i=</code><code>0</code><code>; i<msgListJa.length(); i++){</code>
<code> </code><code>JSONObject msgJo = msgListJa.getJSONObject(i);</code>
<code> </code><code>//去除輪詢的請求</code>
<code> </code><code>if</code><code>(</code><code>"findMessage"</code><code>.equals(msgJo.getString(</code><code>"action"</code><code>))){</code>
<code> </code><code>continue</code><code>;</code>
<code> </code><code>if</code><code>(result.size()==</code><code>0</code><code>){</code>
<code> </code><code>result.add(msgJo);</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>boolean</code> <code>add = </code><code>false</code><code>;</code>
<code> </code><code>for</code><code>(</code><code>int</code> <code>j=</code><code>0</code><code>;j<result.size();j++){</code>
<code> </code><code>JSONObject tempMsgJo = result.get(j);</code>
<code> </code><code>if</code><code>(tempMsgJo.getLong(</code><code>"time"</code><code>)>=msgJo.getLong(</code><code>"time"</code><code>)){</code>
<code> </code><code>result.add(j, msgJo);</code>
<code> </code><code>add = </code><code>true</code><code>;</code>
<code> </code><code>break</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>if</code><code>(!add){</code>
<code> </code><code>result.add(msgJo);</code>
<code> </code><code>return</code> <code>result;</code>
<code>}</code>
邏輯是什麼呢?這麼說你就懂了,在還是寫信通訊的年代,負責通訊的就是郵局,郵局是怎麼處理事務的呢?
發件人把信投遞到郵局,郵局根據收件人位址進行分類,然後由不同的郵差分别送到各個收件人的家裡,
這裡情況比較特殊,就是當某些地方郵局不派送信件的地方,當地人怎麼取信呢?當有同村的進城的時候就拜托他到郵局看看有沒有自己的信件有的話就帶回來。
我們上面的代碼就是類似後面這種特俗情況。
每個用戶端,每隔一段時間都發送一個請求到伺服器詢問有沒有自己的信件,有的話就打包全部接收進來。
每次發送信件出去也是一樣,可能有多個資訊同時被投遞,交給伺服器去分類儲存。
這個代碼實在沒啥說的~基本上邏輯一目了然~
然後怎麼用呢?編譯後注冊成為插件就可以使用了~當然要用到項目中需要自己對消息隊列進行持久化和線程同步互斥的管理,不然并發多了隊列可能就會混亂的喲~~
本文轉自 雄霸天下啦 51CTO部落格,原文連結:http://blog.51cto.com/10549520/1885069,如需轉載請自行聯系原作者