如何给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;
        }
}

逻辑是什么呢?这么说你就懂了,在还是写信通讯的年代,负责通讯的就是邮局,邮局是怎么处理事务的呢?

发件人把信投递到邮局,邮局根据收件人地址进行分类,然后由不同的邮递员分别送到各个收件人的家里,

这里情况比较特殊,就是当某些地方邮局不派送信件的地方,当地人怎么取信呢?当有同村的进城的时候就拜托他到邮局看看有没有自己的信件有的话就带回来。

我们上面的代码就是类似后面这种特俗情况。

每个客户端,每隔一段时间都发送一个请求到服务器询问有没有自己的信件,有的话就打包全部接收进来。

每次发送信件出去也是一样,可能有多个信息同时被投递,交给服务器去分类保存。

这个代码实在没啥说的~基本上逻辑一目了然~

然后怎么用呢?编译后注册成为插件就可以使用了~当然要用到项目中需要自己对消息队列进行持久化和线程同步互斥的管理,不然并发多了队列可能就会混乱的哟~~

时间: 2024-10-13 00:56:14

如何给FineReport设置自定义消息提醒工具的相关文章

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

Windows 7系统有个“计划任务”功能,一般人都很少使用.其实,“计划任务”是系统自带的一个很实用的功能,比如说,这个功能可以设置定时提醒,这样在使用电脑时就不会因为太过投入而导致错过重要的事务.下面,小编就介绍一下这个“计划任务”功能的具体使用方法. 工具/原料 Windows 7计划任务 方法/步骤 1 单击开始菜单,在最下方的搜索框里搜索“计划任务”,再单击打开“任务计划程序”. 2 在“任务计划程序”窗口单击“创建基本任务”,打开“创建基本任务向导”.   输入任务的“名称”以及“描

通达OA 在项目讨论区里,讨论完之后会发送事务提醒,怎么设置事务提醒

通达OA 在项目讨论区里,讨论完之后会发送事务提醒,怎么设置事务提醒: 1.在系统管理-信息交流设置-短信提醒设置中把"项目管理"这一项对应的提醒设置一下即可. 允许是显示这个选项 ,,默认事务提醒是默认勾选状态 电子邮件 这个选项也是这个道理

zabbix 如何设置邮件提醒

前言:公司需要培养新人搭建zabbix,按照文档可以搭建成功,但是遇到搭建邮件提醒的时候总是出问题,所以这里单独拿出来编写一下zabbix如何设置邮件提醒. 前提:搭建好了zabbix_server和zabbix_agent 并且正确设置trigger,在控制面板上有提醒. 一.设置zabbix控制面板 1.1 进入 mediatype 点击Administration-Media types 1.2 设置一个新的mediatype 点击右上角create media type,输入形式按照下图

RTX消息提醒工具设计文档

为什么要做 项目上线后,系统依然由各业务模块负责人自己维护.而后台运行的各种业务服务结果,不能及时反馈到业务负责人.而等到客户反馈时则会太被动.为了能及时发现并解决项目问题,设计了该工具. 可利用资源 1.公司内不能连接外网,沟通主要使用RTX.可以提供RTX服务器信息 2.公司内可以直接连到生产环境. 怎么做1.软件结构图 2.时时获取服务日志 开发环境可以直接连接到生产环境,则可以通过一个独立线程定时获取错误日志信息.错误日志信息包括:错误模块,错误描述.3.配置RTX与业务模块的关系 RT

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

结果: 1.二个按钮可以新建消息提醒,最小化也是新建消息提醒. 2.程序必须最小化后才能点击消息提醒Label2才会有反映. 实例代码: 1 unit Unit1; 2 3 interface 4 5 uses 6 System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialog

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

转自:http://blog.csdn.net/panshiqu/article/details/9369891# 将多个工具条同时并列停靠在某窗口的某一条边上.对于这种停靠方法,利用上述工具条控制函数DockControlBar的lpRect参数,通过控制工具条的停靠矩形区域的方法可以实现 1:在MainFrm.h中增加如下成员函数定义 // 增加 public: void DockControlBarLeftOf(CToolBar* bar, CToolBar* leftof); . 2:在

zabbix监控系统的实际应用(客户端安装-基本应用设置-报警提醒篇)

linux主机代理安装: 接上篇,下面是zabix如何添加监控主机: 组态-主机-创建主机 添加模版: 查看图形: windows主机代理安装: 程序 下载zabbix-2.4.5.tar.gz     解压缩后将zabbix-2.2.5\bin\win64\{zabbix_agentd.exe,zabbix_get.exe,zabbix_sender.exe}三个程序复制到C:\zabbix\目录里 配置 将abbix-2.2.5\conf\zabbix_agentd.win.conf放到C:

调用系统时间dialog(TimePicker),并设置定时提醒功能

/** * 顯示時間選擇dialog */ private void showTimePickerDialog() { Calendar calendar = Calendar.getInstance(); int hour=calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); final TimePickerDialog timePickerDialog = new TimePickerD

详解慢查询日志的相关设置及mysqldumpslow工具

概述 mysql慢查询日志是mysql提供的一种日志记录,它是用来记录在mysql中相应时间超过阈值的语句,就是指运行时间超过long_query_time值的sql,会被记录在慢查询日志中.long_query_time的默认值是10,意思是运行10S之上的语句. 今天主要介绍怎么用mysqldumpslow工具来监控慢查询日志. 一.慢查询日志的相关设置 1.查看是否开启慢查询日志: show variables like '%slow_query_log%'; 2.配置文件设置 #设置慢查