由于业务需要,需要java后台定时的生成图表并发送钉钉。在网上搜索了半天,没发现非常好的解决方案。从echarts-java中得到启发,可以定义一个html模板,将图表先画好了,再通过java输入输出流读取html模板内容(如果需要后台数据,则此时可以做数据动态载入)重新生成生成html页面,html页面挺好,还可以对图表进行各种操作。想保存为图片的话,可以用Phantomjs打开本地网页进行截图。很简单啊,不用像网上说的在后台组装optionjava对象然后再转成json,很麻烦。。。。
所以解决本需求的关键还是前端生成echart网页报表,然后对网页进行截图
思路如下:
该需求可分为四个部分:
按照正常的前端echarts开发流程,将echarts开发好。如果需要动态传值的,可以用${}(自定义即可,不是固定形式)事先在html模板中定义一下,作为标记(如${sendedNum}),然后后台在读取模板中的内容后,将自定义的${}替换成需要的值即可。
前端HTML页面中的js
也可以将绘制echarts封装成一个方法,然后直接替换方法中的参数
2. Java后台用输入输出流读取模板,并将数据传递给模板,生成HTML文件(生成的html文件需要存储在本地),该文件打开后可以看到echarts图表
如果需要动态传值供模板中的echarts使用的话,需要将上一步骤中定义的标记替换掉。
后端java
将自定义的标记替换为需要的值,注意需要先将值转为json字符串再替换
下面代码中的template为echarts html模板的文件名,本模板我是放在项目的classpath下的,所以通过此种方式获取
1. 下载Phantomjs(下载地址:http://phantomjs.org/download.html)并将其放到指定目录
2. 编写js文件用于对生成的html文件进行截图(建议将图片保存为PNG格式),下面是简单用法,具体的可参考其api(http://phantomjs.org/api/):
Open方法打开指定页面并进行截图,render是对指定网页进行截图,并保存为PNG格式
需要传递参数的话,按如下方法获取参数
3. java后台调用Phantomjs,执行截图命令(需要本地磁盘空间用于存储截图后的图片)
如果js中需要传递参数,则只需要在js文件后加上参数即可(js文件后需要加空格,参数之间需要空格)
Phantomjs javascript样例,脚本文件名capturePicFromHtml.js,本例子支持传参:
var page = require('webpage').create();
var system = require('system');
if (system.args.length < 3 || system.args.length > 3) {
console.log('PARAMETER IS NOT CORRECT (> _ <)');
console.log('The correct usage is following...');
console.log("Usage: capturePicFromHtml.js LOCAL_HTML_FILE_PATH OUTPUT_IMAGE_FILE_PATH");
console.log(" Parameter 'LOCAL_HTML_FILE_PATH': local html file path(path + file name + .html)");
console.log(" Parameter 'OUTPUT_IMAGE_FILE_PATH': image file output path(path + image file name + image extension)");
console.log("Example: capturePicFromHtml.js C:/jsp-report/html-output/xxxx.html C:/jsp-report/report/image/xxxx.JPEG");
phantom.exit(1);
} else {
var localHtml = system.args[1];
var outImage = system.args[2];
console.log('PARAMETER IS CORRECT (@^@)');
console.log('local html file path:' + localHtml);
console.log('image file out path:' + outImage);
//viewportSize being the actual size of the headless browser
page.viewportSize = { width: 1524, height: 768 };
page.open('file:///' + localHtml, function(status) {
console.log(status);
setTimeout(function() {
page.render(outImage);
phantom.exit();
}, 10000);
});
}
本部分可以根据自己需要选择图片存储方式
1. 定义一个图片访问接口(从mangodb读取图片,图片格式建议PNG),接口接收图片的uuid,该接口需要外网可以访问
接口样例:http://xxxxx/image.png?imageId=
2. 使用钉钉机器人接口以markdown的消息类型发送消息(使用钉钉SDK)
Markdown类型消息发送方式,样例
package com.dingtalk.chatbot.demo;
import com.dingtalk.chatbot.DingtalkChatbotClient;
import com.dingtalk.chatbot.SendResult;
import com.dingtalk.chatbot.message.MarkdownMessage;
import org.junit.Test;
import java.net.URLEncoder;
import java.util.ArrayList;
/**
* Created by dustin on 2017/3/18.
*/
public class MarkdownMessageTest {
private DingtalkChatbotClient client = new DingtalkChatbotClient();
@Test
public void testSendMarkdownMessage() throws Exception {
MarkdownMessage message = new MarkdownMessage();
message.setTitle("This is a markdown message");
message.add(MarkdownMessage.getHeaderText(1, "header 1"));
message.add(MarkdownMessage.getHeaderText(2, "header 2"));
message.add(MarkdownMessage.getHeaderText(3, "header 3"));
message.add(MarkdownMessage.getHeaderText(4, "header 4"));
message.add(MarkdownMessage.getHeaderText(5, "header 5"));
message.add(MarkdownMessage.getHeaderText(6, "header 6"));
message.add(MarkdownMessage.getReferenceText("reference text"));
message.add("\n\n");
message.add("normal text");
message.add("\n\n");
message.add(MarkdownMessage.getBoldText("Bold Text"));
message.add("\n\n");
message.add(MarkdownMessage.getItalicText("Italic Text"));
message.add("\n\n");
ArrayList orderList = new ArrayList();
orderList.add("order item1");
orderList.add("order item2");
message.add(MarkdownMessage.getOrderListText(orderList));
message.add("\n\n");
ArrayList unorderList = new ArrayList();
unorderList.add("unorder item1");
unorderList.add("unorder item2");
message.add(MarkdownMessage.getUnorderListText(unorderList));
message.add("\n\n");
message.add(MarkdownMessage.getImageText("http://img01.taobaocdn.com/top/i1/LB1GCdYQXXXXXXtaFXXXXXXXXXX"));
message.add(MarkdownMessage.getLinkText("This is a link", "dtmd://dingtalkclient/sendMessage?content=linkmessage"));
message.add(MarkdownMessage.getLinkText("中文跳转", "dtmd://dingtalkclient/sendMessage?content=" + URLEncoder.encode("链接消息", "UTF-8")));
SendResult result = client.send(TestConfig.CHATBOT_WEBHOOK, message);
System.out.println(result);
}
}