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. Windows 7上执行Cake 报错原因是Powershell 版本问题

    在Windows 7 SP1 电脑上执行Cake的的例子 http://cakebuild.net/docs/tutorials/getting-started ,运行./Build.ps1 报下面的 ...

  2. 关于这段时间学习 EntityFramework的 一点感悟

    Ado.Net,用了N多年,Entity Framework也关注了很多年. 每当项目转型的时候,就花费大巴的时间,学习一番,潮流的东西. 这个Orm很多,这个EF很火,这么多年了,我还是不敢用,虽然 ...

  3. ExtJS 4.2 业务开发(三)数据添加和修改

    接上面的船舶管理业务,这里介绍添加和修改操作. 目录 1. 添加操作 2. 修改操作 3. 在线演示 1. 添加操作 1.1 创建AddShipWindow.js 在业务中的view目录下创建一个Ad ...

  4. hadoop2.7之Mapper/reducer源码分析

    一切从示例程序开始: 示例程序 Hadoop2.7 提供的示例程序WordCount.java package org.apache.hadoop.examples; import java.io.I ...

  5. jQuery幻灯片插件autoPic

    原文地址:Jquery自定义幻灯片插件 插件效果图: 演示地址:autoPic项目地址:autoPic 欢迎批评指正!

  6. C# 实时折线图,波形图

    此Demo是采用VS自带的Chart图表控件,制作实时动态显示的折线图,和波形图. 涉及到知识如下: Chart 控件,功能强大,可以绘制柱状图,折线图,波形图,饼状图,大大简化了对图的开发与定制. ...

  7. GJM : C#设计模式汇总整理——导航 【原创】

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  8. Android之SharedPreferences数据存储

    一.SharedPreferences保存数据介绍 如果有想要保存的相对较小键值集合,应使用SharedPreferences API.SharedPreferences对象指向包含键值对的文件并提供 ...

  9. iOS7 NavigationController 手势问题

    在iOS7中,如果使用了UINavigationController,那么系统自带的附加了一个从屏幕左边缘开始滑动可以实现pop的手势.但是,如果自定义了navigationItem的leftBarB ...

  10. kafka

    2016-11-13  20:48:43 简单说明什么是kafka? Apache kafka是消息中间件的一种,我发现很多人不知道消息中间件是什么,在开始学习之前,我这边就先简单的解释一下什么是消息 ...