方法之前我们先说一下设计思路,有了好设计思路我们才能去写好一个程序
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-初步思路