如何給FineReport設定自定義訊息提醒工具

傑華園發表於2016-12-22

FineReport設計器有自動的訊息推送功能可設定報表定時推送和常規的日報週報推送。官方有自己的訊息推送的介面,不過有些使用者旺旺希望自己開發,符合自己需求的推送介面。

下面這個方案就從邏輯層面簡單闡述一個通訊類應該怎麼實現。

廢話不多說直接上程式碼,為了保證新手能夠看懂,這個程式碼基本上只需要瞭解JSJQ的常規寫法就行。


點選(此處)摺疊或開啟

  1. ;
  2. (function($){
  3.         /*定義一個工具物件,所有的工具以後都放進去*/
  4.         HG = {};
  5.         /*定義我們第一個基礎類OBJ*/
  6.         HG.OBJ = function(options){
  7.                 //保證子類能夠繼承父類的預設成員變數
  8.                 this.options = $.extend(this._defaultOptions(), options);
  9.                 //初始化物件
  10.                 this._init();
  11.         };
  12.         $.extend(HG.OBJ.prototype, {
  13.                 _defaultOptions: function () {
  14.                         return {classType:"OBJ"};
  15.                 },
  16.                 _init:function(){}
  17.         });
  18.         /*定義用於生成子類的方法*/
  19.         HG.extend=function(parent,options){
  20.                 var son = $.extend(parent,{});
  21.                 son.prototype = $.extend(parent.prototype,options);
  22.                 return son;
  23.         };
  24.         /*第一個就是要構建我們的通訊物件*/
  25.         /****定義一些通訊用的私有成員和方法*****/
  26.         //傳送通道的狀態,為了減輕伺服器壓力,採取單通道傳送
  27.         var status = true;
  28.         var sendMsgList = [];
  29.         var receiveMsgList = [];
  30.         var server = null;
  31.         var sendType = null;
  32.         var dataType = null;
  33.         //最終傳送訊息的方法
  34.         var send=function(msg,onReceive,onComplete,onFailed){
  35.                 if(!msg.inList){
  36.                         msg.inList = true;
  37.                         sendMsgList.push(msg);
  38.                 }
  39.                 if(status){
  40.                         status = false;
  41.                         var tempSendMsgList = sendMsgList;
  42.                         sendMsgList = [];
  43.                         FR.ajax({
  44.                                 url: server,
  45.                                 type: sendType,
  46.                                 dataType:dataType,
  47.                                 data:{msgList:tempSendMsgList},
  48.                                 success : function(receiveMsgList){
  49.                                         status = true;
  50.                                         onReceive(receiveMsgList);
  51.                                 },
  52.                                 complete: function(XMLHttpRequest,textStatus){
  53.                                         status = true;
  54.                                         onComplete(XMLHttpRequest,textStatus);
  55.                                 },
  56.                                 error: function(XMLHttpRequest, textStatus, errorThrown){
  57.                                         status = true;
  58.                                         onFailed(XMLHttpRequest, textStatus, errorThrown);
  59.                                 }
  60.                         });
  61.                 }else{
  62.                         setTimeout(function(){
  63.                                 send(msg,onReceive,onComplete,onFailed);
  64.                         },1000);
  65.                 }
  66.         };
  67.         var formatDate = function(date){
  68.                 var d = new Date(date);
  69.                 return d.getFullYear()+"-"+d.getMonth()+"-"+d.getDate()+" "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds();
  70.         };
  71.         //通訊類,可以自己重寫onReceive的方法來實現自己的訊息工具,訊息的內容為JSON格式,自己定義就好了
  72.         HG.CommunicationClient = HG.extend(HG.OBJ,{
  73.                 _defaultOptions: function () {
  74.                         return {
  75.                                 classType:"CommunicationClient",
  76.                                 //預設只跟當前的伺服器進行聯絡
  77.                                 server:FR.servletURL+"?op=msgserver",
  78.                                 sendType:"POST",
  79.                                 dataType:"JSON",
  80.                                 //輪詢的頻率,預設3秒1次,越快伺服器和客戶端壓力越大
  81.                                 pollingRate:3000
  82.                         };
  83.                 },
  84.                 _init:function(){
  85.                         server = this.options.server;
  86.                         sendType = this.options.sendType;
  87.                         dataType = this.options.dataType;
  88.                         this.polling4Receive();
  89.                 },
  90.                 send:function(msg){
  91.                         var self = this;
  92.                         send(msg,self.onReceive, self.onComplete, self.onFailed);
  93.                 },
  94.                 //給某個使用者發文字訊息
  95.                 sendText:function(toUserId,text){
  96.                         this.send({action:"send",userId:toUserId,time:new Date().getTime(),content:{text:text}})
  97.                 },
  98.                 onReceive:function(msg){
  99.                         if(msg.length>0){
  100.                                 for( var i=0; i<msg.length; i++ ){
  101.                                         console.info(formatDate(msg[i].time)+" "+msg[i].name+" "+decodeURI("%E8%AF%B4%EF%BC%9A")+" "+msg[i].content.text);
  102.                                 }
  103.                         }
  104.                 },
  105.                 onFailed:function(XMLHttpRequest, textStatus, errorThrown){
  106.                 },
  107.                 onComplete:function(XMLHttpRequest, textStatus){
  108.                 },
  109.                 /*向伺服器輪詢,檢查是否有自己的訊息*/
  110.                 polling4Receive:function(){
  111.                         var self = this;
  112.                         self.send({action:"findMessage",inList:false});
  113.                         setTimeout(function(){
  114.                                 self.polling4Receive();
  115.                         },self.options.pollingRate);
  116.                 }
  117.         });
  118.         //先生成一個對話工具
  119.         HG.Talk = new HG.CommunicationClient();
  120. })(jQuery);


在任意一個你需要的系統或者介面引入這段JS

然後最基本的文字訊息傳送

                                                HG.Talk.sendText(接收者的使用者名稱,文字訊息的內容);

當然,我們實際需求中需要的遠遠不止是發個文字這麼簡單,對於任意訊息的傳送該怎麼搞呢?

有兩種方法:

繼承HG.CommunicationClient實現新的自己的通訊類,或者重寫 HG.Talk的方法,兩種方式都是修改onReceive方法,上面的程式碼中是把訊息直接顯示到控制檯當中的。

你可以根據你自己的需要傳送任意JSON格式的msg並在onReceive中去實現你想要的展現方法。當然如果你想真正的瞭解它是怎麼運作的,可以花5分鐘看一遍程式碼就清楚了

下面看看後臺,因為暫時只說邏輯,所以很多東西都不考慮,後臺就會非常的簡單,只需要有點JAVA基礎,並且瞭解FineReportservice介面就應該能看懂.


點選(此處)摺疊或開啟

  1. package com.hg.plugin.plate.msgutils;
  2.  
  3. import java.io.PrintWriter;
  4. import java.util.ArrayList;
  5. import java.util.Date;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9.  
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12.  
  13. import com.fr.fs.control.UserControl;
  14. import com.fr.fs.web.service.ServiceUtils;
  15. import com.fr.json.JSONArray;
  16. import com.fr.json.JSONObject;
  17. import com.fr.stable.fun.Service;
  18. import com.fr.web.utils.WebUtils;
  19.  
  20. public class MessageServer implements Service {
  21.         
  22.         class Message{
  23.                 private long time = -1;
  24.                 private String fuserId = "";
  25.                 private String tuserId = "";
  26.                 private JSONObject content = JSONObject.create();
  27.                 
  28.                 public Message(String fromUserId,String toUserId,JSONObject content){
  29.                         this.fuserId = fromUserId;
  30.                         this.tuserId = toUserId;
  31.                         this.content = content;
  32.                         time = new Date().getTime();
  33.                 }
  34.                 
  35.                 public JSONObject toJSON() throws Exception{
  36.                         JSONObject jo = JSONObject.create();
  37.                         jo.put("userId", fuserId);
  38.                         jo.put("name", UserControl.getInstance().getByUserName(fuserId).getRealname());
  39.                         jo.put("content", content);
  40.                         jo.put("time", time);
  41.                         return jo;
  42.                 }
  43.         }
  44.         
  45.         private static Map<String,List<Message>> messageStore = new HashMap<String,List<Message>>();
  46.         
  47.         @Override
  48.         public String actionOP() {
  49.                 return "msgserver";
  50.         }
  51.         
  52.         @Override
  53.         public void process(HttpServletRequest req, HttpServletResponse res,String op, String sessionID) throws Exception {
  54.                 String msgListStr = WebUtils.getHTTPRequestParameter(req, "msgList");
  55.                 JSONArray msgListJa = new JSONArray(msgListStr);
  56.                 List<JSONObject> msgList = sortMessageList(msgListJa);
  57.                 String fromUserId = ServiceUtils.getCurrentUserName(req);
  58.                 //投遞給別人的信件
  59.                 for(JSONObject msg : msgList){
  60.                         String tuserId = msg.getString("userId");
  61.                         if(!messageStore.containsKey(tuserId)){
  62.                                 messageStore.put(tuserId, new ArrayList<Message>());
  63.                         }
  64.                         messageStore.get(tuserId).add(new Message(fromUserId,tuserId,msg.getJSONObject("content")));
  65.                 }
  66.                 //檢視是否有自己的信件
  67.                 if(!messageStore.containsKey(fromUserId)){
  68.                         messageStore.put(fromUserId, new ArrayList<Message>());
  69.                 }
  70.                 List<Message> sendList = messageStore.get(fromUserId);
  71.                 JSONArray result = JSONArray.create();
  72.                 for(Message msg : sendList){
  73.                         result.put(msg.toJSON());
  74.                 }
  75.                 messageStore.put(fromUserId, new ArrayList<Message>());
  76.                 res.setContentType("text/html;charset=UTF-8");
  77.                 res.setCharacterEncoding("UTF-8");
  78.                 PrintWriter write = res.getWriter();
  79.                 write.write(result.toString());
  80.                 write.flush();
  81.                 write.close();
  82.         }
  83.         
  84.         private static List<JSONObject> sortMessageList(JSONArray msgListJa) throws Exception{
  85.                 List<JSONObject> result = new ArrayList<JSONObject>();
  86.                 for(int i=0; i<msgListJa.length(); i++){
  87.                         JSONObject msgJo = msgListJa.getJSONObject(i);
  88.                         //去除輪詢的請求
  89.                         if("findMessage".equals(msgJo.getString("action"))){
  90.                                 continue;
  91.                         }
  92.                         if(result.size()==0){
  93.                                 result.add(msgJo);
  94.                         }else{
  95.                                 boolean add = false;
  96.                                 for(int j=0;j<result.size();j++){
  97.                                         JSONObject tempMsgJo = result.get(j);
  98.                                         if(tempMsgJo.getLong("time")>=msgJo.getLong("time")){
  99.                                                 result.add(j, msgJo);
  100.                                                 add = true;
  101.                                                 break;
  102.                                         }
  103.                                 }
  104.                                 if(!add){
  105.                                         result.add(msgJo);
  106.                                 }
  107.                         }
  108.                 }
  109.                 return result;
  110.         }
  111. }
邏輯是什麼呢?這麼說你就懂了,在還是寫信通訊的年代,負責通訊的就是郵局,郵局是怎麼處理事務的呢?


發件人把信投遞到郵局,郵局根據收件人地址進行分類,然後由不同的郵遞員分別送到各個收件人的家裡,

這裡情況比較特殊,就是當某些地方郵局不派送信件的地方,當地人怎麼取信呢?當有同村的進城的時候就拜託他到郵局看看有沒有自己的信件有的話就帶回來。

我們上面的程式碼就是類似後面這種特俗情況。

每個客戶端,每隔一段時間都傳送一個請求到伺服器詢問有沒有自己的信件,有的話就打包全部接收進來。

每次傳送信件出去也是一樣,可能有多個資訊同時被投遞,交給伺服器去分類儲存。

這個程式碼實在沒啥說的~基本上邏輯一目瞭然~

然後怎麼用呢?編譯後註冊成為外掛就可以使用了~當然要用到專案中需要自己對訊息佇列進行持久化和執行緒同步互斥的管理,不然併發多了佇列可能就會混亂的喲~~

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21472864/viewspace-2131203/,如需轉載,請註明出處,否則將追究法律責任。

相關文章