java后台生成echarts图片
由于最近项目需要在java后台生成echarts图片,花时间研究了下这个,顺便分享下;
1.首先需要先下载echarts本地服务器;
可以去官网下载也可以直接去我的网盘下载 ,也可以去这个官网下载最新的 https://www.jianshu.com/p/dfc28fd7d786
(1)网盘:链接:https://pan.baidu.com/s/1kTZ9JWsU48PTTG809HurRA 提取码:b69t
(2)获取后放入本地解压到例如D:/TEST下
D:\TEST\phantomjs-2.1.1-windows\bin\phantomjs.exe D:\TEST\saintlee-echartsconvert-master\echartsconvert\echarts-convert.js -s -p 6666
解压之后可以使用cmd命令启动这个服务,输入以上命令出现 echarts-convert server start success. [pid]=10500 提示即启动成功;
2.此服务启动成功后就是代码了
以下是springboot项目整体结构了采用了Maven导包方式,需要utils下和pom文件需要导入相应的包
(1)导入pom.xml包
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.7</version> </dependency> <!-- 阿里JSON解析器 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.68</version> </dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
(2)3个工具类分别如下,根据需求可自行修改逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | package com.lxp.demo.utils; /** * @projectName: ruoyi * @packageName: com.rmis.common.utils.chart * @className: HttpUtil * @description: ${description} * @author: hrs * @date: 2020-07-16 15:25 */ 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; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; 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 (Map.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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package com.lxp.demo.utils; /** * @projectName: ruoyi * @packageName: com.rmis.common.utils.chart * @className: FreemarkerUtil * @description: ${description} * @author: hrs * @date: 2020-07-16 15:26 */ import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.Map; /** * @author msh * @date2020/7/16 */ 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.setClassForTemplateLoading(FreemarkerUtil. class ,templateDirectory); // 生成模板对象 Template template = configuration.getTemplate(templateFileName); // 将datas写入模板并返回 try (StringWriter stringWriter = new StringWriter()) { template.process(datas, stringWriter); stringWriter.flush(); return stringWriter.getBuffer().toString(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | package com.lxp.demo.utils; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import freemarker.template.TemplateException; import org.apache.http.client.ClientProtocolException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sun.misc.BASE64Decoder; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author msh * @date2020/7/16 */ public class EchartsUtil { /** * 临时文件夹路径 */ public static final String TEMP_FILE_PATH = "D:/tempFile/" ; private static final String SUCCESS_CODE = "1" ; private static final Logger logger = LoggerFactory.getLogger(EchartsUtil. class ); 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( "http://localhost:6666" , 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; } public static void getImage(Map<String, Object> datas) throws IOException { // 生成option字符串 String option = null ; try { if (!datas.containsKey( "ftl" )){ logger.error( "没有指定生成图表的模板!" ); } option = FreemarkerUtil.generateString((String) datas.get( "ftl" ), "/template" , datas); } catch (TemplateException e) { logger.error(e.getMessage()); } // 根据option参数 String base64 = generateEchartsBase64(option); File file = new File(TEMP_FILE_PATH); if (!file.exists()) { // 如果不存在就创建文件 file.mkdir(); } BASE64Decoder decoder = new BASE64Decoder(); try (OutputStream out = new FileOutputStream(TEMP_FILE_PATH+ "test.jpg" )){ // 解密 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(); } } } |
以上是所有工具类的代码,解释基本都有,最后还需要一个echarts图模板 option.ftl 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | { title: { text: '功率调节计算' }, tooltip: { trigger: 'axis' }, legend: { data: [ 'AO' , 'AO*' ] }, xAxis: { type: 'category' , boundaryGap: false , data: ${aohour} }, yAxis: { type: 'value' }, series: [ { name: 'AO' , type: 'line' , stack: '总量' , data: ${aoList}, smooth : true }, { name: 'AO*' , type: 'line' , stack: '总量' , data: ${aoxList}, smooth : true }, ] } |
(3)最后一部是执行EchartUtils的测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static void main(String[] args) { //制造数据 List<String> aoxList = new ArrayList<>(); aoxList.add( "2" ); aoxList.add( "4" ); aoxList.add( "7" );aoxList.add( "9" ); aoxList.add( "10" ); aoxList.add( "9" ); aoxList.add( "8" ); aoxList.add( "8" ); aoxList.add( "7" ); List<String> aoList = new ArrayList<>(); aoList.add( "1" ); aoList.add( "4" ); aoList.add( "7" );aoList.add( "9" ); aoList.add( "10" ); aoList.add( "10" ); aoList.add( "10" ); aoList.add( "10" ); aoList.add( "10" ); List<String> aohour = new ArrayList<>(); aohour.add( "1" );aohour.add( "2" );aohour.add( "3" );aohour.add( "4" );aohour.add( "5" );aohour.add( "6" );aohour.add( "7" ); aohour.add( "8" );aohour.add( "9" ); // 模板参数 HashMap<String, Object> datas = new HashMap<>(); //aohour、aoList、aoxList对应模板/template/option.ftl中的x和y轴的名字,模板可自行修改, //ftl 为设置模板的名字。路径在/templates下 datas.put( "aoxList" , JSON.toJSONString(aoxList)); datas.put( "aoList" , JSON.toJSONString(aoList)); datas.put( "aohour" , JSON.toJSONString(aohour)); datas.put( "ftl" , "option.ftl" ); try { EchartsUtil.getImage(datas); } catch (IOException e) { e.printStackTrace(); } } |
执行后在代码设置的路径下会生成这样的图片及完成功能,后续会继续如何将图片以及文字替换掉word模板文档中的字和图片
标签:
java后台生成echarts图片
, springboot
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」