JAVA后台生成echarts并截图发送钉钉之解决方案

1 篇文章 0 订阅
1 篇文章 0 订阅

由于业务需要,需要java后台定时的生成图表并发送钉钉。在网上搜索了半天,没发现非常好的解决方案。从echarts-java中得到启发,可以定义一个html模板,将图表先画好了,再通过java输入输出流读取html模板内容(如果需要后台数据,则此时可以做数据动态载入)重新生成生成html页面,html页面挺好,还可以对图表进行各种操作。想保存为图片的话,可以用Phantomjs打开本地网页进行截图。很简单啊,不用像网上说的在后台组装optionjava对象然后再转成json,很麻烦。。。。

所以解决本需求的关键还是前端生成echart网页报表,然后对网页进行截图

 

思路如下:

该需求可分为四个部分:

一、根据模板生成echart图表(HTML格式)

  1. 绘制echarts的html页面作为模板

按照正常的前端echarts开发流程,将echarts开发好。如果需要动态传值的,可以用${}(自定义即可,不是固定形式)事先在html模板中定义一下,作为标记(如${sendedNum}),然后后台在读取模板中的内容后,将自定义的${}替换成需要的值即可。

前端HTML页面中的js

也可以将绘制echarts封装成一个方法,然后直接替换方法中的参数

<!-- ECharts单文件引入 -->
<script src="/home/bigdata/jsp-report/js/echarts/3.7.1/echarts.min.js"></script>
<script type="text/javascript">
//关键${summaryType} ${data} 要替换的标签
drawCharts(${summaryType}, ${data});

/** 
 * echarts 3.x
 * 绘制图表,summaryType 统计维度, data 数据
**/

function drawCharts(summaryType, data) {

 //自己写吧
}
</script>

2. Java后台用输入输出流读取模板,并将数据传递给模板,生成HTML文件(生成的html文件需要存储在本地),该文件打开后可以看到echarts图表

 

如果需要动态传值供模板中的echarts使用的话,需要将上一步骤中定义的标记替换掉。

后端java

将自定义的标记替换为需要的值,注意需要先将值转为json字符串再替换

下面代码中的template为echarts  html模板的文件名,本模板我是放在项目的classpath下的,所以通过此种方式获取

 

二、使用第三方软件phantomjs对生成的HTML进行截图

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);
	});

}

三、将图片保存到mangodb中并返回图片的uuid

本部分可以根据自己需要选择图片存储方式

四、将图片发送到钉钉(建议使用钉钉提供的SDK来调用机器人接口,此种方式比较方便)

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<String> orderList = new ArrayList<String>();
        orderList.add("order item1");
        orderList.add("order item2");
        message.add(MarkdownMessage.getOrderListText(orderList));
        message.add("\n\n");

        ArrayList<String> unorderList = new ArrayList<String>();
        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);
    }
}

 


  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个需求可以分为以下几个步骤: 1. 使用 Java 代码生成表格图片 2. 调用钉钉群机器人 API 发送通知,附带表格图片 下面是一个简单的示例代码,可以参考实现: ```java import javax.imageio.ImageIO; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.Base64; public class DingtalkBotNotifier { private static final String WEBHOOK_URL = "https://oapi.dingtalk.com/robot/send?access_token=ACCESS_TOKEN"; public static void main(String[] args) throws IOException { // 生成表格图片 BufferedImage image = createTableImage(); // 将图片转成 Base64 编码 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "png", baos); String base64Image = Base64.getEncoder().encodeToString(baos.toByteArray()); // 发送钉钉群机器人通知 sendDingtalkNotification(base64Image); } private static BufferedImage createTableImage() { int columnCount = 3; int rowCount = 5; int cellWidth = 100; int cellHeight = 50; int padding = 10; int borderWidth = 2; int width = columnCount * cellWidth + (columnCount + 1) * padding + 2 * borderWidth; int height = rowCount * cellHeight + (rowCount + 1) * padding + 2 * borderWidth; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); Graphics2D g = image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); g.setColor(Color.BLACK); g.setStroke(new BasicStroke(borderWidth)); for (int i = 0; i <= rowCount; i++) { int y = borderWidth + (i + 1) * padding + i * cellHeight; g.drawLine(borderWidth + padding, y, width - borderWidth - padding, y); } for (int j = 0; j <= columnCount; j++) { int x = borderWidth + (j + 1) * padding + j * cellWidth; g.drawLine(x, borderWidth + padding, x, height - borderWidth - padding); } g.setFont(new Font("Arial", Font.PLAIN, 12)); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { int x = borderWidth + (j + 1) * padding + j * cellWidth; int y = borderWidth + (i + 1) * padding + i * cellHeight; String text = "Cell " + (i + 1) + "," + (j + 1); int textWidth = g.getFontMetrics().stringWidth(text); int textHeight = g.getFontMetrics().getHeight(); g.drawString(text, x + (cellWidth - textWidth) / 2, y + (cellHeight + textHeight) / 2); } } g.dispose(); return image; } private static void sendDingtalkNotification(String base64Image) throws IOException { String message = "这是一个表格图片:\n![table](data:image/png;base64," + base64Image + ")"; String encodedMessage = URLEncoder.encode(message, "UTF-8"); String webhookUrl = WEBHOOK_URL.replace("ACCESS_TOKEN", "YOUR_ACCESS_TOKEN"); URL url = new URL(webhookUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setConnectTimeout(5000); conn.setReadTimeout(5000); String json = "{\"msgtype\":\"text\",\"text\":{\"content\":\"" + encodedMessage + "\"}}"; byte[] bytes = json.getBytes("UTF-8"); conn.getOutputStream().write(bytes); conn.getOutputStream().flush(); conn.getOutputStream().close(); conn.getInputStream().close(); conn.disconnect(); } } ``` 这个示例代码生成一个 3 列 5 行的表格图片,并发送钉钉群机器人通知中。你需要将其中的 `YOUR_ACCESS_TOKEN` 替换成你自己的钉钉群机器人的 access token。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值