如何给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# 将多个工具条同时并列停靠在某窗口的某一条边上.对于这种停靠方法,利用上述工具条控制函 ...
随机推荐
- 《Django By Example》第五章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者@ucag注:大家好,我是新来的翻译, ...
- 【SQLServer】记一次数据迁移-标识重复的简单处理
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 今天在数据迁移的时候因为手贱遇到一个坑爹问题,发来大家乐乐,也传授新手点经验 迁移惯用就 ...
- Android Button的基本使用
title: Android Button的基本使用 tags: Button,按钮 --- Button介绍: Button(按钮)继承自TextView,在Android开发中,Button是常用 ...
- Hawk 6. 高级话题:子流程系统
子流程的定义 当流程设计的越来越复杂,越来越长时,就难以进行管理了.因此,采用模块化的设计才会更加合理.本节我们介绍子流程的原理和使用. 所谓子流程,就是能先构造出一个流程,然后被其他流程调用.被调用 ...
- [C#] C# 知识回顾 - 异常介绍
异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...
- UE4新手引导入门教程
请大家去这个地址下载:file:///D:/UE4%20Doc/虚幻4新手引导入门教程.pdf
- java统计字符串单词的个数
在一些项目中可能需要对一段字符串中的单词进行统计,我在这里写了一个简单的demo,有需要的同学可以拿去看一下. 本人没怎么写个播客,如果有啥说的不对的地方,你来打我啊 不说废话了直接贴代码: 实现代码 ...
- 敏捷软件开发VS传统软件工程
敏捷软件开发:又称敏捷开发,是一种从1990年代开始逐渐引起广泛关注的一些新兴软件开发方法,是一种应对快速变化的需求的一种软件开发能力. 与传统软件工程相比,它们的具体名称.理念.过程.术语都不尽相同 ...
- NYOJ 954
首先观察: 2! = 2×1 = (2)10 = (10)2, 则第一个1是第2位,2!有1个质因数23! = 3×2×1 ...
- Spark Streaming+Kafka
Spark Streaming+Kafka 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端, ...