如何给FineReport设置自定义微信新消息提醒设置工具

如何利用报表工具FineReport实现报表列的动态展示 - 老A不折腾 - 博客园
随笔 - 202, 文章 - 1, 评论 - 7, 引用 - 0
相信动态列的实现困扰了很多人,大数据量,多字段的加载将会非常耗时,数据又做不到真正的动态灵活。现有的方式都是通过变向的隐藏等方式来实现。
那该如何解决呢?这里分享帆软报表设计器FineReport的实现方案,结合实际工作中遇到的的相关内容。
我本地常用数据库是MYSQL,所以比较了解一点,所以实现方式也是基于mysql的。首先了解一下MySQL自带的information_schema数据库使用。
大家在安装或使用MYSQL时,会发现除了自己安装的数据库以外,还有一个 information_schema数据库。information_schema数据库是做什么用的呢,使用WordPress博客的朋友可能会想,是不是安装模板添加的数据库呀?看完本片文章后,你就会对information_schema数据库有所了解。
information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式。什么是元数据呢?元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等。有些时候用于表述该信息的其他术语包括&数据词典&和&系统目录&。
在 MySQL中,把 information_schema 看作是一个数据库,确切说是信息数据库。其中保存着关于MySQL服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等。在INFORMATION_SCHEMA中,有数个只读表。它们实际上是视图,而不是基本表,因此,你将无法看到与之相关的任何文件。
information_schema数据库表说明:
&SCHEMATA表:提供了当前mysql实例中所有数据库的信息。是show databases的结果取之此表。
&TABLES表:提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是show tables from schemaname的结果取之此表。
COLUMNS表:提供了表中的列信息。详细表述了某张表的所有列以及每个列的信息。是show columns from schemaname.tablename的结果取之此表。
STATISTICS表:提供了关于表索引的信息。是show index from schemaname.tablename的结果取之此表。
&USER_PRIVILEGES(用户权限)表:给出了关于全程权限的信息。该信息源自mysql.user授权表。是非标准表。
SCHEMA_PRIVILEGES(方案权限)表:给出了关于方案(数据库)权限的信息。该信息来自mysql.db授权表。是非标准表。
TABLE_PRIVILEGES(表权限)表:给出了关于表权限的信息。该信息源自mysql.tables_priv授权表。是非标准表。
COLUMN_PRIVILEGES(列权限)表:给出了关于列权限的信息。该信息源自mysql.columns_priv授权表。是非标准表。
CHARACTER_SETS(字符集)表:提供了mysql实例可用字符集的信息。是SHOW CHARACTER SET结果集取之此表。
COLLATIONS表:提供了关于各字符集的对照信息。
COLLATION_CHARACTER_SET_APPLICABILITY表:指明了可用于校对的字符集。这些列等效于SHOWCOLLATION的前两个显示字段。
TABLE_CONSTRAINTS表:描述了存在约束的表。以及表的约束类型。
KEY_COLUMN_USAGE表:描述了具有约束的键列。
ROUTINES表:提供了关于存储子程序(存储程序和函数)的信息。此时,ROUTINES表不包含自定义函数(UDF)。名为&mysql.proc name&的列指明了对应于INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。
VIEWS表:给出了关于数据库中的视图的信息。需要有show views权限,否则无法查看视图信息。
TRIGGERS表:提供了关于触发程序的信息。必须有super权限才能查看该表
扩展的应用
查看某个数据库表的记录数
selecttable_schema,table_name,table_rows from tables where TABLE_SCHEMA = '数据库名称' order by table_
查看数据库所占空间
selectconcat(round(sum(data_length/),2),'MB') as data_length_MB,&
concat(round(sum(index_length/),2),'MB')as index_length_MB&
frominformation_schema.tables where&
table_schema='数据库名';
查看某个表所占空间
selectconcat(truncate(sum(data_length)/),'MB') as data_size,
concat(truncate(sum(max_data_length)/),'MB')as max_data_size,
concat(truncate(sum(data_free)/),'MB')as data_free,
concat(truncate(sum(index_length)/),'MB')as index_size
frominformation_schema.tables where TABLE_NAME = '表名';
看完之后相信可能还是有点疑惑。就是说mysql中有一个系统库information_schema。这个库中存放着mysql数据库的数据库实例名,表名称,表注释,字段名称,字段注释等等等等。而这个库的存在为我们动态列的实现就提供了一个基础。(其余的数据库oracle、sqlserver、db2等也有类似的存在。)
然后我们继续回到主题。我在本地建立了一个测试库reporttest,测试表report。在mysql库中新建一个库reporttest(或者使用已经存在的库,但是如果使用已经存在的,那么报表内部sql内容就需要更改。所以最好新建一个),然后用类似navicat的工具运行我提供的reporttest.sql文件,即可建表并且导入数据,然后刷新即可,此时数据准备完成。
设计器创建数据连接test,填写对应的数据库信息,测试成功即OK。
此时,库名称为reporttest,表名称为report,数据连接test。这时直接预览动态列实现方案.cpt。
可以很清晰的看到效果,选择哪个列,它就只查询那个列,只展示哪个列的数据,这就是动态列的实现方案。大家可以依据我的逻辑,替换成自己的数据连接库、表数据进行测试使用体验!Java报表工具FineReport自定义css使用方法【finereport吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:425贴子:
Java报表工具FineReport自定义css使用方法收藏
在实际项目中,为了更符合报表使用者的审美观或者让FineReport报表和总体框架协调,可能需要修改一些页面显示的样式表(css),下面我们就来学习几个例子,来看看如何在Java报表工具FineReport中自定义控件以及填报的css。 1.报表控件,以下拉树控件为例来看看怎样改变下拉树的图标的。第一步:收集好需要使用的图标,推荐大小为16×16,假设想让树叶的图标为leaf.gif;第二步:新建一个文件夹,这里叫custom并把该文件夹放到Web应用目录下(即和WEB-INF平行的地方),将第一步的图标放入该文件夹内;第三步:在custom文件夹内新建一个css文件,比如叫custom_tree. 第四步:custom_tree.css内容如下 .bbit-tree-node-leaf {background:url(“leaf.gif”);} 第五步:打开有使用下拉树控件的报表,依次点击菜单:报表——&报表web属性——&引用css,在控件自定义样式表一览点插入按钮后写上上custom_tree.css的相对路径:custom/custom_tree.css,确定后保存报表。第六步:启动服务器,查看该报表,现在可以看到下拉树叶的图标就是你自定义的图标了。下面附上树控件中比较关键的几个css .bbit-tree-node-expanded .bbit-tree-node-icon //节点展开的样式 .bbit-tree-node-leaf .bbit-tree-node-icon // 树叶的样式 .bbit-tree-node-collapsed .bbit-tree-node-icon // 闭合的样式 .bbit-tree-node-loading .bbit-tree-node-icon //正在加载的样式2.报表填报,来看看把焦点框变成红色的步骤第一步:新建一个叫文件夹,这里用一个叫write的文件夹做示例,同样的把该文件夹放到Web应用目录下;第二步:在write文件夹中新建一个叫custom_cell.css的样式表文件;第三步:在custom_cell.css中写入以下内容.fDtop, .fDbottom, .fDleft, .fDright, .fDdot{border:1}第四步:打开报表。依次点击菜单:报表——&报表web属性——&引用css,在填报自定义样式表一览点插入按钮后写上上custom_cell.css的相对路径:write/custom_cell.css,确定后保存报表。第五步:启动服务器查看此报表,可以看到填报的编辑框变成了红色边框。同理:冻结先也可以按照类似的步骤进行自定义。
登录百度帐号精彩文章推荐&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
如何给FineReport设置自定义消息提醒工具
摘要:FineReport设计器有自动的消息推送功能,可设置报表定时推送和常规的日报周报推送。官方有自己的消息推送的接口,不过有些用户旺旺希望自己开发,符合自己需求的推送界面。下面这个方案就从逻辑层面简单阐述一个通讯类应该怎么实现。废话不多说直接上代码,为了保证新手能够看懂,这个代码基本上只需要了解JS和JQ的常规写法就行。```;(function($){/*定义一个工具对象,所有的工具以后都放进去*/HG={};/*定义我们第一个基础类OBJ*/HG.OBJ=function(
FineReport设计器有自动的消息推送功能,可设置报表定时推送和常规的日报周报推送。官方有自己的消息推送的接口,不过有些用户旺旺希望自己开发,符合自己需求的推送界面。
下面这个方案就从逻辑层面简单阐述一个通讯类应该怎么实现。
废话不多说直接上代码,为了保证新手能够看懂,这个代码基本上只需要了解JS和JQ的常规写法就行。
(function($){
/*定义一个工具对象,所有的工具以后都放进去*/
/*定义我们第一个基础类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);
/*第一个就是要构建我们的通讯对象*/
/****定义一些通讯用的私有成员和方法*****/
//发送通道的状态,为了减轻服务器压力,采取单通道发送
var status =
var sendMsgList = [];
var receiveMsgList = [];
var server =
var sendType =
var dataType =
//最终发送消息的方法
var send=function(msg,onReceive,onComplete,onFailed){
if(!msg.inList){
msg.inList =
sendMsgList.push(msg);
if(status){
var tempSendMsgList = sendMsgL
sendMsgList = [];
url: server,
type: sendType,
dataType:dataType,
data:{msgList:tempSendMsgList},
success : function(receiveMsgList){
onReceive(receiveMsgList);
complete: function(XMLHttpRequest,textStatus){
onComplete(XMLHttpRequest,textStatus);
error: function(XMLHttpRequest, textStatus, errorThrown){
onFailed(XMLHttpRequest, textStatus, errorThrown);
setTimeout(function(){
send(msg,onReceive,onComplete,onFailed);
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 () {
classType:&CommunicationClient&,
//默认只跟当前的服务器进行联络
server:FR.servletURL+&?op=msgserver&,
sendType:&POST&,
dataType:&JSON&,
//轮询的频率,默认3秒1次,越快服务器和客户端压力越大
pollingRate:3000
_init:function(){
server = this.options.
sendType = this.options.sendT
dataType = this.options.dataT
this.polling4Receive();
send:function(msg){
var self =
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. 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 =
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.
import java.io.PrintW
import java.util.ArrayL
import java.util.D
import java.util.HashM
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import javax.servlet.http.HttpServletR
import com.fr.fs.control.UserC
import com.fr.fs.web.service.ServiceU
import com.fr.json.JSONA
import com.fr.json.JSONO
import com.fr.stable.fun.S
import com.fr.web.utils.WebU
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 =
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);
private static Map
<string,list
& messageStore = new HashMap
<string,list
public String actionOP() {
return &msgserver&;
public void process(HttpServletRequest req, HttpServletResponse res,String op, String sessionID) throws Exception {
String msgListStr = WebUtils.getHTTPRequestParameter(req, &msgList&);
JSONArray msgListJa = new JSONArray(msgListStr);
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
messageStore.get(tuserId).add(new Message(fromUserId,tuserId,msg.getJSONObject(&content&)));
//查看是否有自己的信件
if(!messageStore.containsKey(fromUserId)){
messageStore.put(fromUserId, new ArrayList
sendList = messageStore.get(fromUserId);
JSONArray result = JSONArray.create();
for(Message msg : sendList){
result.put(msg.toJSON());
messageStore.put(fromUserId, new ArrayList
res.setContentType(&text/charset=UTF-8&);
res.setCharacterEncoding(&UTF-8&);
PrintWriterwrite = res.getWriter();
write.write(result.toString());
write.flush();
write.close();
private static List
sortMessageList(JSONArray msgListJa) throws Exception{
result = new ArrayList
for(int i=0; i
<msglistja.length(); i++){
JSONObject msgJo = msgListJa.getJSONObject(i);
//去除轮询的请求
if(&findMessage&.equals(msgJo.getString(&action&))){
if(result.size()==0){
result.add(msgJo);
boolean add =
for(int j=0;j
<result.size();j++){
JSONObject tempMsgJo = result.get(j);
if(tempMsgJo.getLong(&time&)&=msgJo.getLong(&time&)){
result.add(j, msgJo);
result.add(msgJo);
逻辑是什么呢?这么说你就懂了,在还是写信通讯的年代,负责通讯的就是邮局,邮局是怎么处理事务的呢?
发件人把信投递到邮局,邮局根据收件人地址进行分类,然后由不同的邮递员分别送到各个收件人的家里,
这里情况比较特殊,就是当某些地方邮局不派送信件的地方,当地人怎么取信呢?当有同村的进城的时候就拜托他到邮局看看有没有自己的信件有的话就带回来。
我们上面的代码就是类似后面这种特俗情况。
每个客户端,每隔一段时间都发送一个请求到服务器询问有没有自己的信件,有的话就打包全部接收进来。
每次发送信件出去也是一样,可能有多个信息同时被投递,交给服务器去分类保存。
这个代码实在没啥说的~基本上逻辑一目了然~
然后怎么用呢?编译后注册成为插件就可以使用了~当然要用到项目中需要自己对消息队列进行持久化和线程同步互斥的管理,不然并发多了队列可能就会混乱的哟~~
</result.size();j++){
</string,list
</string,list
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
邮箱低至5折
推荐购买再奖现金,最高25%
&200元/3月起
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
如何给FineReport设置自定义消息提醒工具相关信息,包括
的信息,所有如何给FineReport设置自定义消息提醒工具相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International}

我要回帖

更多关于 闲鱼消息提醒设置 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信