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中手机录屏并转换GIF的两种方式

    之前在博文中为了更好的给大家演示APP的实现效果,本人了解学习了几种给手机录屏的方法,今天就给大家介绍两种我个人用的比较舒服的两种方法: (1)配置adb环境后,使用cmd命令将手机界面操作演示存为视 ...

  2. javascript:逆波兰式表示法计算表达式结果

    逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 -  等价于   5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...

  3. nodejs利用http模块实现银行卡所属银行查询和骚扰电话验证

    http模块内部封装了http服务器和客户端,因此Node.js不需要借助Apache.IIS.Nginx.Tomcat等传统HTTP服务器,就可以构建http服务器,亦可以用来做一些爬虫.下面简单介 ...

  4. [C#] 走进 LINQ 的世界

    走进 LINQ 的世界 序 在此之前曾发表过三篇关于 LINQ 的随笔: 进阶:<LINQ 标准查询操作概述>(强烈推荐) 技巧:<Linq To Objects - 如何操作字符串 ...

  5. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  6. 内存映射文件MemoryMappedFile使用

    参考资料: http://blog.csdn.net/bitfan/article/details/4438458 所谓内存映射文件,其实就是在内存中开辟出一块存放数据的专用区域,这区域往往与硬盘上特 ...

  7. .NET面试题集锦②(Part 二)

    一.前言部分 文中的问题及答案多收集整理自网络,不保证100%准确,还望斟酌采纳. 1.实现产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复. ]; ArrayList my ...

  8. H3 BPM让天下没有难用的流程之功能介绍

    H3 BPM10.0功能地图如下:  图:H3 BPM 功能地图 一.流程引擎 H3  BPM 流程引擎遵循WFMC 标准的工作流引擎技术,设计可运行的流程和表单,实现工作任务在人与人.人与系统.系统 ...

  9. 类型转换器(InitBinder 初始化绑定器)

    单日期格式 导入jar包 创建FirstController.java @Controller public class FirstController { /** * @param binder * ...

  10. Flux 普及读本

    话说当时做 APP 时,三月不知肉味,再次将眼光投放前端,有种天上一天,地下一年的感觉. Flux 是一种思想 了解的最好方式当然是看Flux官方文档了.React 中文站点也能找到对应的翻译版本,但 ...