使用PhantomJSI在java后端生成ECharts图片

方法之前我们先说一下设计思路,有了好设计思路我们才能去写好一个程序
1.初步思路
①Web项目提供一个http服务,并公开此url地址,访问该地址可以获取Echarts统计图;
②Java通过Runtime调用phantomjs脚本,并传入url和filename参数,相当于打开浏览器;
③使用page.open(url)打开该地址,相当于在浏览器中浏览访问;
④使用page.render(filename)生成图片,相当于截图保存;
⑤Java读取filename图片文件File,将其转换成Base64字符串即可。
2.中期思路
①Java通过Runtime调用phantomjs脚本,传入ECharts的option和filename参数;
②使用page.open(about:blank)打开空页面;
③调用page.evaluate()在空页面上创建ECharts的Dom层和JavaScript代码;
④使用page.render(filename)生成图片;
⑤Java读取filename图片文件File,将其转换成Base64字符串即可。
2.中期思路
①使用server.listen()开启Web服务。
②java通过url请求地址,并传入ECharts的option参数;
③使用page.open(about:blank)打开空页面;
④ 调用page.evaluate()在空页面上创建ECharts的Dom层和JavaScript代码;
⑤使用page.renderBase64(format)生成图片的Base64字符串;
⑥response返回Base64数据。

有了思路我们写一下具体实现
一、phantomjs、EChartsConvert下载
1.下载、解压
链接:https://pan.baidu.com/s/1v1r4K0JztR-yuYW8NGXesw
提取码:y8jv
2.配置环境变量
cmd–>set path=%path%;E:\applications\phantomjs-2.1.1\bin
3.运行
<phantomjs路径> <EChartsConvert路径> -s -p <服务端口号>
例如:phantomjs E:\applications\phantomjs-2.1.1\echartsconvert\echarts-convert.js -s -p 6666
出现success表示成功,成功后别关cmd窗口
在这里插入图片描述
二、java代码
1.maven项目,结构如图
在这里插入图片描述
2.工具类
Http工具类

package com.mosband.genechars.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

public class HttpUtil {

    public static String post(String url, Map<String, String> params, String charset)
            throws ClientProtocolException, IOException {
        String responseEntity = "";

        // 创建CloseableHttpClient对象
        CloseableHttpClient client = HttpClients.createDefault();

        // 创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);

        // 生成请求参数
        List<NameValuePair> nameValuePairs = new ArrayList<>();
        if (params != null) {
            for (Entry<String, String> entry : params.entrySet()) {
                nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
        }

        // 将参数添加到post请求中
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, charset));

        // 发送请求,获取结果(同步阻塞)
        CloseableHttpResponse response = client.execute(httpPost);

        // 获取响应实体
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 按指定编码转换结果实体为String类型
            responseEntity = EntityUtils.toString(entity, charset);
        }

        // 释放资源
        EntityUtils.consume(entity);
        response.close();

        return responseEntity;
    }
}

Freemarker工具类

package com.mosband.genechars.util;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Map;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class FreemarkerUtil {
    private static final String path = FreemarkerUtil.class.getClassLoader().getResource("").getPath();

    public static String generateString(String templateFileName, String templateDirectory, Map<String, Object> datas)
            throws IOException, TemplateException {
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_0);

        // 设置默认编码
        configuration.setDefaultEncoding("UTF-8");

        // 设置模板所在文件夹
        configuration.setDirectoryForTemplateLoading(new File(path + templateDirectory));

        // 生成模板对象
        Template template = configuration.getTemplate(templateFileName);

        // 将datas写入模板并返回
        try (StringWriter stringWriter = new StringWriter()) {
            template.process(datas, stringWriter);
            stringWriter.flush();
            return stringWriter.getBuffer().toString();
        }
    }
}

生成Echarts工具类

package com.mosband.genechars.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.client.ClientProtocolException;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class EchartsUtil {
    private static String url = "http://localhost:6666";
    private static final String SUCCESS_CODE = "1";

    public static String generateEchartsBase64(String option) throws ClientProtocolException, IOException {
        String base64 = "";
        if (option == null) {
            return base64;
        }
        option = option.replaceAll("\\s+", "").replaceAll("\"", "'");

        // 将option字符串作为参数发送给echartsConvert服务器
        Map<String, String> params = new HashMap<>();
        params.put("opt", option);
        String response = HttpUtil.post(url, params, "utf-8");

        // 解析echartsConvert响应
        JSONObject responseJson = JSON.parseObject(response);
        String code = responseJson.getString("code");

        // 如果echartsConvert正常返回
        if (SUCCESS_CODE.equals(code)) {
            base64 = responseJson.getString("data");
        }
        // 未正常返回
        else {
            String string = responseJson.getString("msg");
            throw new RuntimeException(string);
        }

        return base64;
    }
}

FreeMarker Template Language(FTL)文本

{
    title: {
        text:'${title}',
        x:'middle',
        textAlign:'center'
    },
    xAxis: {
        type: 'category',
        data: ${categories}
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        data: ${values},
        type: 'bar'
    }]
}

测试类

package com.mosband.genechars.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;

import org.apache.http.client.ClientProtocolException;

import com.alibaba.fastjson.JSON;
import com.mosband.genechars.util.EchartsUtil;
import com.mosband.genechars.util.FreemarkerUtil;

import freemarker.template.TemplateException;
import sun.misc.BASE64Decoder;

public class App {
    public static void main(String[] args) throws ClientProtocolException, IOException, TemplateException {
        // 变量
        String title = "水果";
        String[] categories = new String[] { "苹果", "香蕉", "西瓜" };
        int[] values = new int[] { 3, 2, 1 };

        // 模板参数
        HashMap<String, Object> datas = new HashMap<>();
        datas.put("categories", JSON.toJSONString(categories));
        datas.put("values", JSON.toJSONString(values));
        datas.put("title", title);

        // 生成option字符串
        String option = FreemarkerUtil.generateString("option.ftl", "/com/mosband/genechars/template", datas);

        // 根据option参数
        String base64 = EchartsUtil.generateEchartsBase64(option);
        
        System.out.println("BASE64:" + base64);
        generateImage(base64, "C:/Users/admin/Desktop/test.png");
    }

    public static void generateImage(String base64, String path) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        try (OutputStream out = new FileOutputStream(path)){
            // 解密
            byte[] b = decoder.decodeBuffer(base64);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
        } 
    }
}

三、运行结果
在这里插入图片描述
四、参考文档:
https://www.jianshu.com/p/dfc28fd7d786?tdsourcetag=s_pcqq_aiomsg
https://gitee.com/saintlee/echartsconvert?tdsourcetag=s_pcqq_aiomsg#31-初步思路

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值