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设置自定义消息提醒工具的更多相关文章

  1. FadeTop – 定时休息提醒工具

    FadeTop 是款定时休息提醒工具,其特色是当设定时间到达时,将桌面渐变为指定的颜色,强制提醒但不影响桌面的任何操作 FadeTop is a visual break reminder for W ...

  2. 巧用Windows 7计划任务设置定时提醒

    Windows 7系统有个“计划任务”功能,一般人都很少使用.其实,“计划任务”是系统自带的一个很实用的功能,比如说,这个功能可以设置定时提醒,这样在使用电脑时就不会因为太过投入而导致错过重要的事务. ...

  3. 使用quartz.net 完成一个winform版的任务提醒工具

    这个任务提醒工具是这样的,是每日定时执行,触发时间为 小时和分钟.每天早上来就可以把当天要做的添加到datagridview中,只记录了标题和内容和时间.双击dgv就查看内容. 如果每天计划重复,也可 ...

  4. Android实例-设置消息提醒(XE8+小米2)

    相关资料: 1.官网实例:http://docwiki.embarcadero.com/RADStudio/XE5/en/Mobile_Tutorial:_Using_the_Notification ...

  5. [整理+原创]ubuntu Thunderbird Mail设置自动提醒

    开机启动的设置方法 // 在终端输入 gnome-session-properties 然后添加thunderbird为启动项 方法1——自动提醒 下载插件:Thunderbird Mail客户端菜单 ...

  6. Powerpoint 演示时定时提醒工具

    经常碰到这样的场景,规定的演讲报告时间所剩无几,甚至是已经超时,但演讲者并不知情,做为主持人只能从旁边轻轻的善意的提醒,但有时演讲者会没注意到主持人的提醒... 这里要介绍的就是这样一款用于提醒演讲者 ...

  7. 关于android闹钟,设置定时提醒的一点心得

    首先在设置提醒之前你需要一个入口,比如说onclick事件中,在此不做赘述. android中使用闹钟进行提醒其实非常简单,你只需要告知系统你想在什么时候被提醒,然后需要一个闹钟的广播接收器,当到你设 ...

  8. docker搭建gitlab,设置邮件提醒,并运行runner

    接着http://www.cnblogs.com/wsy1030/p/8431837.html 在另一台机子运行gitlab: docker run --name='gitlab' -d -p 222 ...

  9. MFC文档应用程序CToolBar:设置两个工具条并列停靠到同一条边上 转

    转自:http://blog.csdn.net/panshiqu/article/details/9369891# 将多个工具条同时并列停靠在某窗口的某一条边上.对于这种停靠方法,利用上述工具条控制函 ...

随机推荐

  1. [虾扯蛋] android界面框架-Window

    从纯sdk及framwork的角度看,android中界面框架相关的类型有:Window,WindowManager,View等.下面就以这几个类为出发点来概览下安卓开发的"界面架构&quo ...

  2. 恢复SQL Server被误删除的数据(再扩展)

    恢复SQL Server被误删除的数据(再扩展) 大家对本人之前的文章<恢复SQL Server被误删除的数据> 反应非常热烈,但是文章里的存储过程不能实现对备份出来的日志备份里所删数据的 ...

  3. (JS+CSS)实现图片放大效果

    代码很简单,在这里就不过多阐述,先上示例图: 实现过程: html部分代码很简单 <div id="outer"> <p>点击图片</p> &l ...

  4. Mysql存储引擎及选择方法

    0x00 Mysql数据库常用存储引擎 Mysql数据库是一款开源的数据库,支持多种存储引擎的选择,比如目前最常用的存储引擎有:MyISAM,InnoDB,Memory等. MyISAM存储引擎 My ...

  5. 【NLP】干货!Python NLTK结合stanford NLP工具包进行文本处理

    干货!详述Python NLTK下如何使用stanford NLP工具包 作者:白宁超 2016年11月6日19:28:43 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的 ...

  6. OpenLiveWriter代码插件

    1.OpenLiveWriter安装 Windows Live Writer在2012年就停止了更新,Open Live Writer(以下简称OLW)是由Windows Live WriterWri ...

  7. C#与C++通信

    # C#与C++相互发送消息 # ## C#端: ## namespace CshapMessage { /// /// MainWindow.xaml 的交互逻辑 /// public partia ...

  8. mount报错: you must specify the filesystem type

    在linux mount /dev/vdb 到 /home 分区时报错: # mount /dev/vdb /homemount: you must specify the filesystem ty ...

  9. java常用的设计模式

    设计模式:一个程序员对设计模式的理解:"不懂"为什么要把很简单的东西搞得那么复杂.后来随着软件开发经验的增加才开始明白我所看到的"复杂"恰恰就是设计模式的精髓所 ...

  10. Javascript中的valueOf与toString

    基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...