如何给FineReport设置自定义消息提醒工具
FineReport设计器有自动的消息推送功能,可设置报表定时推送和常规的日报周报推送。官方有自己的消息推送的接口,不过有些用户旺旺希望自己开发,符合自己需求的推送界面。
下面这个方案就从逻辑层面简单阐述一个通讯类应该怎么实现。
废话不多说直接上代码,为了保证新手能够看懂,这个代码基本上只需要了解JS和JQ的常规写法就行。
;
(function($){
        /*定义一个工具对象,所有的工具以后都放进去*/
        HG = {};
        /*定义我们第一个基础类OBJ*/
        HG.OBJ = function(options){
                //保证子类能够继承父类的默认成员变量
                this.options = $.extend(this._defaultOptions(), options);
                //初始化对象
                this._init();
        };
        $.extend(HG.OBJ.prototype, {
                _defaultOptions: function () {
                        return {classType:"OBJ"};
                },
                _init:function(){}
        });
        /*定义用于生成子类的方法*/
        HG.extend=function(parent,options){
                var son = $.extend(parent,{});
                son.prototype = $.extend(parent.prototype,options);
                return son;
        };
        /*第一个就是要构建我们的通讯对象*/
        /****定义一些通讯用的私有成员和方法*****/
        //发送通道的状态,为了减轻服务器压力,采取单通道发送
        var status = true;
        var sendMsgList = [];
        var receiveMsgList = [];
        var server = null;
        var sendType = null;
        var dataType = null;
        //最终发送消息的方法
        var send=function(msg,onReceive,onComplete,onFailed){
                if(!msg.inList){
                        msg.inList = true;
                        sendMsgList.push(msg);
                }
                if(status){
                        status = false;
                        var tempSendMsgList = sendMsgList;
                        sendMsgList = [];
                        FR.ajax({  
                                url: server,  
                                type: sendType,
                                dataType:dataType,
                                data:{msgList:tempSendMsgList},
                                success : function(receiveMsgList){
                                        status = true;
                                        onReceive(receiveMsgList);
                                },
                                complete: function(XMLHttpRequest,textStatus){
                                        status = true;
                                        onComplete(XMLHttpRequest,textStatus);
                                },
                                error: function(XMLHttpRequest, textStatus, errorThrown){
                                        status = true;
                                        onFailed(XMLHttpRequest, textStatus, errorThrown);
                                }
                        });
                }else{
                        setTimeout(function(){
                                send(msg,onReceive,onComplete,onFailed);
                        },1000);
                }
        };
        var formatDate = function(date){
                var d = new Date(date);
                return d.getFullYear()+"-"+d.getMonth()+"-"+d.getDate()+"  "+d.getHours()+":"+d.getMinutes()+":"+d.getSeconds();
        };
        //通讯类,可以自己重写onReceive的方法来实现自己的消息工具,消息的内容为JSON格式,自己定义就好了
        HG.CommunicationClient = HG.extend(HG.OBJ,{
                _defaultOptions: function () {
                        return {
                                classType:"CommunicationClient",
                                //默认只跟当前的服务器进行联络
                                server:FR.servletURL+"?op=msgserver",
                                sendType:"POST",
                                dataType:"JSON",
                                //轮询的频率,默认3秒1次,越快服务器和客户端压力越大
                                pollingRate:3000
                        };
                },
                _init:function(){
                        server = this.options.server;
                        sendType = this.options.sendType;
                        dataType = this.options.dataType;
                        this.polling4Receive();
                },
                send:function(msg){
                        var self = this;
                        send(msg,self.onReceive, self.onComplete, self.onFailed);
                },
                //给某个用户发文本消息
                sendText:function(toUserId,text){
                        this.send({action:"send",userId:toUserId,time:new Date().getTime(),content:{text:text}})
                },
                onReceive:function(msg){
                        if(msg.length>0){
                                for( var i=0; i<msg.length; i++ ){
                                        console.info(formatDate(msg[i].time)+"  "+msg[i].name+" "+decodeURI("%E8%AF%B4%EF%BC%9A")+" "+msg[i].content.text);
                                }
                        }
                },
                onFailed:function(XMLHttpRequest, textStatus, errorThrown){
                },
                onComplete:function(XMLHttpRequest, textStatus){
                },
                /*向服务器轮询,检查是否有自己的消息*/
                polling4Receive:function(){
                        var self = this;
                        self.send({action:"findMessage",inList:false});
                        setTimeout(function(){
                                self.polling4Receive();
                        },self.options.pollingRate);
                }
        });
        //先生成一个对话工具
        HG.Talk = new HG.CommunicationClient();
})(jQuery);
在任意一个你需要的系统或者界面引入这段JS,
然后最基本的文本消息发送
HG.Talk.sendText(接收者的用户名,文本消息的内容);
当然,我们实际需求中需要的远远不止是发个文本这么简单,对于任意消息的发送该怎么搞呢?
有两种方法:
继承HG.CommunicationClient实现新的自己的通讯类,或者重写 HG.Talk的方法,两种方式都是修改onReceive方法,上面的代码中是把消息直接显示到控制台当中的。
你可以根据你自己的需要发送任意JSON格式的msg并在onReceive中去实现你想要的展现方法。当然如果你想真正的了解它是怎么运作的,可以花5分钟看一遍代码就清楚了
下面看看后台,因为暂时只说逻辑,所以很多东西都不考虑,后台就会非常的简单,只需要有点JAVA基础,并且了解FineReport的service接口就应该能看懂.
package com.hg.plugin.plate.msgutils;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fr.fs.control.UserControl;
import com.fr.fs.web.service.ServiceUtils;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.stable.fun.Service;
import com.fr.web.utils.WebUtils;
public class MessageServer implements Service {
        class Message{
                private long time = -1;
                private String fuserId = "";
                private String tuserId = "";
                private JSONObject content = JSONObject.create();
                public Message(String fromUserId,String toUserId,JSONObject content){
                        this.fuserId = fromUserId;
                        this.tuserId = toUserId;
                        this.content = content;
                        time = new Date().getTime();
                }
                public JSONObject toJSON() throws Exception{
                        JSONObject jo = JSONObject.create();
                        jo.put("userId", fuserId);
                        jo.put("name", UserControl.getInstance().getByUserName(fuserId).getRealname());
                        jo.put("content", content);
                        jo.put("time", time);
                        return jo;
                }
        }
        private static Map<String,List<Message>> messageStore = new HashMap<String,List<Message>>();
        @Override
        public String actionOP() {
                return "msgserver";
        }
        @Override
        public void process(HttpServletRequest req, HttpServletResponse res,String op, String sessionID) throws Exception {
                String msgListStr = WebUtils.getHTTPRequestParameter(req, "msgList");
                JSONArray msgListJa = new JSONArray(msgListStr);
                List<JSONObject> msgList = sortMessageList(msgListJa);
                String fromUserId = ServiceUtils.getCurrentUserName(req);
                //投递给别人的信件
                for(JSONObject msg : msgList){
                        String tuserId = msg.getString("userId");
                        if(!messageStore.containsKey(tuserId)){
                                messageStore.put(tuserId, new ArrayList<Message>());
                        }
                        messageStore.get(tuserId).add(new Message(fromUserId,tuserId,msg.getJSONObject("content")));
                }
                //查看是否有自己的信件
                if(!messageStore.containsKey(fromUserId)){
                        messageStore.put(fromUserId, new ArrayList<Message>());
                }
                List<Message> sendList = messageStore.get(fromUserId);
                JSONArray result = JSONArray.create();
                for(Message msg : sendList){
                        result.put(msg.toJSON());
                }
                messageStore.put(fromUserId, new ArrayList<Message>());
                res.setContentType("text/html;charset=UTF-8");
                res.setCharacterEncoding("UTF-8");
                PrintWriter  write = res.getWriter();
                write.write(result.toString());
                write.flush();
                write.close();
        }
        private static List<JSONObject> sortMessageList(JSONArray msgListJa) throws Exception{
                List<JSONObject> result = new ArrayList<JSONObject>();
                for(int i=0; i<msgListJa.length(); i++){
                        JSONObject msgJo = msgListJa.getJSONObject(i);
                        //去除轮询的请求
                        if("findMessage".equals(msgJo.getString("action"))){
                                continue;
                        }
                        if(result.size()==0){
                                result.add(msgJo);
                        }else{
                                boolean add = false;
                                for(int j=0;j<result.size();j++){
                                        JSONObject tempMsgJo = result.get(j);
                                        if(tempMsgJo.getLong("time")>=msgJo.getLong("time")){
                                                result.add(j, msgJo);
                                                add = true;
                                                break;
                                        }
                                }
                                if(!add){
                                        result.add(msgJo);
                                }
                        }
                }
                return result;
        }
}
逻辑是什么呢?这么说你就懂了,在还是写信通讯的年代,负责通讯的就是邮局,邮局是怎么处理事务的呢?
发件人把信投递到邮局,邮局根据收件人地址进行分类,然后由不同的邮递员分别送到各个收件人的家里,
这里情况比较特殊,就是当某些地方邮局不派送信件的地方,当地人怎么取信呢?当有同村的进城的时候就拜托他到邮局看看有没有自己的信件有的话就带回来。
我们上面的代码就是类似后面这种特俗情况。
每个客户端,每隔一段时间都发送一个请求到服务器询问有没有自己的信件,有的话就打包全部接收进来。
每次发送信件出去也是一样,可能有多个信息同时被投递,交给服务器去分类保存。
这个代码实在没啥说的~基本上逻辑一目了然~
然后怎么用呢?编译后注册成为插件就可以使用了~当然要用到项目中需要自己对消息队列进行持久化和线程同步互斥的管理,不然并发多了队列可能就会混乱的哟~~
如何给FineReport设置自定义消息提醒工具的更多相关文章
- FadeTop – 定时休息提醒工具
		
FadeTop 是款定时休息提醒工具,其特色是当设定时间到达时,将桌面渐变为指定的颜色,强制提醒但不影响桌面的任何操作 FadeTop is a visual break reminder for W ...
 - 巧用Windows 7计划任务设置定时提醒
		
Windows 7系统有个“计划任务”功能,一般人都很少使用.其实,“计划任务”是系统自带的一个很实用的功能,比如说,这个功能可以设置定时提醒,这样在使用电脑时就不会因为太过投入而导致错过重要的事务. ...
 - 使用quartz.net 完成一个winform版的任务提醒工具
		
这个任务提醒工具是这样的,是每日定时执行,触发时间为 小时和分钟.每天早上来就可以把当天要做的添加到datagridview中,只记录了标题和内容和时间.双击dgv就查看内容. 如果每天计划重复,也可 ...
 - Android实例-设置消息提醒(XE8+小米2)
		
相关资料: 1.官网实例:http://docwiki.embarcadero.com/RADStudio/XE5/en/Mobile_Tutorial:_Using_the_Notification ...
 - [整理+原创]ubuntu Thunderbird Mail设置自动提醒
		
开机启动的设置方法 // 在终端输入 gnome-session-properties 然后添加thunderbird为启动项 方法1——自动提醒 下载插件:Thunderbird Mail客户端菜单 ...
 - Powerpoint 演示时定时提醒工具
		
经常碰到这样的场景,规定的演讲报告时间所剩无几,甚至是已经超时,但演讲者并不知情,做为主持人只能从旁边轻轻的善意的提醒,但有时演讲者会没注意到主持人的提醒... 这里要介绍的就是这样一款用于提醒演讲者 ...
 - 关于android闹钟,设置定时提醒的一点心得
		
首先在设置提醒之前你需要一个入口,比如说onclick事件中,在此不做赘述. android中使用闹钟进行提醒其实非常简单,你只需要告知系统你想在什么时候被提醒,然后需要一个闹钟的广播接收器,当到你设 ...
 - docker搭建gitlab,设置邮件提醒,并运行runner
		
接着http://www.cnblogs.com/wsy1030/p/8431837.html 在另一台机子运行gitlab: docker run --name='gitlab' -d -p 222 ...
 - MFC文档应用程序CToolBar:设置两个工具条并列停靠到同一条边上  转
		
转自:http://blog.csdn.net/panshiqu/article/details/9369891# 将多个工具条同时并列停靠在某窗口的某一条边上.对于这种停靠方法,利用上述工具条控制函 ...
 
随机推荐
- 懒加载session 无法打开 no session or session was closed  解决办法(完美解决)
			
首先说明一下,hibernate的延迟加载特性(lazy).所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作.因为hibernate当中支持实体对象,外键会与实体对象关联起来.如 ...
 - 使用UIBezierPath绘制图形
			
当需要画图时我们一般创建一个UIView子类, 重写其中的drawRect方法 再drawRect方法中利用UIBezierPath添加画图 UIBezierPath的使用方法: (1)创建一个Bez ...
 - iOS可视化动态绘制八种排序过程
			
前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...
 - Python的单元测试(一)
			
title: Python的单元测试(一) author: 青南 date: 2015-02-27 22:50:47 categories: Python tags: [Python,单元测试] -- ...
 - CRL快速开发框架系列教程六(分布式缓存解决方案)
			
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
 - Discuz论坛黑链清理教程
			
本人亲测有效,原创文章哦~~~ 论坛黑链非常的麻烦,如果你的论坛有黑链,那么对不起,百度收录了你的黑链,不会自动删除,需要你手动去清理. 什么是黑链 黑链,顾名思义,就是一些赌博网站的外链,这些黑链相 ...
 - iptables
			
一.在服务器上打开 22.80.9011端口: iptables -A INPUT -p tcp --dport 9011 -j ACCEPT iptables -A OUTPUT -p tcp -- ...
 - Java实现Excel中的NORMSDIST函数和NORMSINV函数
			
由于工作中需要将Excel中的此两种函数转换成java函数,从而计算内部评级的资本占用率和资本占用金额.经过多方查阅资料和整理,总结出如下两个转换方法 标准正态分布累计函数NORMSDIST: pub ...
 - JAVA装饰者模式(从现实生活角度理解代码原理)
			
装饰者模式可以动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 该模式的适用环境为: (1)在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职 ...
 - A*算法应用[转]
			
转自:http://www.cnblogs.com/zhoug2020/p/3468167.html 这是一篇十分精彩/易懂的博客,感谢原博主!本文通过自己的理解在原博文基础上突出一些重点字眼,句子. ...