返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java生成Echarts表图的两种方案
  • 514
分享到

Java生成Echarts表图的两种方案

javaecharts开发语言 2023-09-08 18:09:53 514人浏览 独家记忆
摘要

最近被生成报告纠结了一个礼拜,生成Word并不难,可以通过模版来实现,目前用得比较多的技术有,poi,freemarker等等工具,只需要自己写一个模版通过占位符的形式来替换里面的变量。这里生成wor

最近被生成报告纠结了一个礼拜,生成Word并不难,可以通过模版来实现,目前用得比较多的技术有,poi,freemarker等等工具,只需要自己写一个模版通过占位符的形式来替换里面的变量。这里生成word就不过多去介绍(后期出一篇文章)但是里面的图表就没有那么好去实现,要考虑到通过后台获取数据来生成图表。经过了一个礼拜的查阅资料找到了两种在后端实现方式,本篇以生成柱状图为例:

一 Jfreechart

  1. 简介
    JFreeChart是JAVA平台上的一个开放的图表绘制类库。它完全使用JAVA语言编写,是为applications, applets, servlets 以及jsP等使用所设计。JFreeChart可生成饼图(pie charts)、柱状图(bar charts)、散点图(scatter plots)、时序图(time series)、甘特图(Gantt charts)等等多种图表,并且可以产生PNG和JPEG格式的输出,还可以与pdfexcel关联。
  2. 导入依赖
 <dependency>            <groupId>jfreechart</groupId>            <artifactId>jfreechart</artifactId>            <version>1.0.0</version>        </dependency>
  1. 简单demo
     public static JFreeChart createChart(CateGoryDataset categoryDataset) {        JFreeChart jfreechart = ChartFactory.createBarChart("Test", "", "", categoryDataset,                PlotOrientation.VERTICAL, false, false, false);        Font labelFont = new Font(Font.SANS_SERIF, Font.TRUETYPE_FONT, 15);//        Font labelFont1 = new Font(Font.SANS_SERIF, Font.TRUETYPE_FONT, 24);//         jfreechart.setTextAntiAlias(false);        jfreechart.setBackgroundPaint(Color.white);        // 获得图表区域对象        CategoryPlot plot = jfreechart.getCategoryPlot();        // 设置横虚线可见        plot.setRangeGridlinesVisible(true);        // 虚线色彩        plot.setRangeGridlinePaint(Color.gray);        // 数据轴精度        NumberAxis vn = (NumberAxis) plot.getRangeAxis();        DecimalFORMat df = new DecimalFormat("#0.0");        // 数据轴数据标签的显示格式        vn.setNumberFormatOverride(df);        // x轴设置        CategoryAxis domainAxis = plot.getDomainAxis();        // 轴标题        domainAxis.setLabelFont(labelFont);        // 轴数值        domainAxis.setTickLabelFont(labelFont);        // X轴标题过长可设置倾斜度          domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 3.0));        // 横轴上的 Label        domainAxis.setMaximumCategoryLabelWidthRatio(6.00f);        // 是否完整显示        // 设置距离图片左端距离        domainAxis.setLowerMargin(0.0);        // 设置距离图片右端距离        domainAxis.setUpperMargin(0.0);        // 设置 columnKey 是否间隔显示        plot.setDomainAxis(domainAxis);        // 设置柱图背景色(注意,系统取色的时候要使用16位的模式来查看颜色编码,这样比较准确)        plot.setBackgroundPaint(new Color(255, 255, 255, 255));        // y轴设置        ValueAxis rangeAxis = plot.getRangeAxis();        rangeAxis.setLabelFont(labelFont);        rangeAxis.setTickLabelFont(labelFont);        // 设置最高的一个 Item 与图片顶端的距离        rangeAxis.setUpperMargin(0.15);        // 设置最低的一个 Item 与图片底端的距离        rangeAxis.setLowerMargin(0.15);        plot.setRangeAxis(rangeAxis);        // 解决中文乱码问题(关键)        TextTitle textTitle = jfreechart.getTitle();        textTitle.setFont(new Font("黑体", Font.PLAIN, 20));        domainAxis.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 15));        domainAxis.setLabelFont(new Font("宋体", Font.PLAIN, 15));        vn.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 15));        vn.setLabelFont(new Font("黑体", Font.PLAIN, 15));        // 使用自定义的渲染器        CustomRenderer renderer = new CustomRenderer();        ArrayList<Double> data = new ArrayList<Double>();        data.add(99D);        data.add(87D);        data.add(89D);        data.add(45D);        data.add(78D);        data.add(92D);        data.add(98D);        data.add(80D);        renderer.setScores(data);        // 设置柱子宽度        renderer.setMaximumBarWidth(0.1);        // 设置柱子高度        renderer.setMinimumBarLength(0.1);        // 设置柱子边框颜色        renderer.setBaseOutlinePaint(Color.BLACK);        // 设置柱子边框可见        renderer.setDrawBarOutline(true);        // 设置每个地区所包含的平行柱的之间距离        renderer.setItemMargin(1);        jfreechart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);        // 显示每个柱的数值,并修改该数值的字体属性//          renderer.setIncludeBaseInRange(true);        renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());        renderer.setBaseItemLabelsVisible(true);        plot.setRenderer(renderer);        // 设置柱的透明度        plot.setForegroundAlpha(1.0f);        // 背景色 透明度        plot.setBackgroundAlpha(0.5f);        return jfreechart;    }
       public static CategoryDataset createDataset() {         double[][] data = new double[][]{{1,9,0,15,9,3,4}};        String[] rowKeys = {"1"};        String[] columnKeys = {"Test1","Test2","Test3","Test4","Test5","Test6","Test7"};        return DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data);    }
  1. 启动测试
    public static void main(String[] args) throws Exception {        // 创建CategoryDataset对象        CategoryDataset dataset = createDataset();        // 根据Dataset 生成JFreeChart对象,并设置相应的样式        JFreeChart freeChart = createChart(dataset);        FileOutputStream out = null;        try {            out = new FileOutputStream("F:\\chart110605.png");            ChartUtilities.writeChartAsPNG(out, freeChart,                    800, 450);// 输出图表            System.out.println("图片运行成功");        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                out.close();            } catch (final Exception ex) {                ex.printStackTrace();            }        }    }
  1. 生成图片展示
    在这里插入图片描述
    第一种方式到此为止,下面上第二种

Echarts插件

  1. 简介
    Echarts在熟悉了解前端的一定不会感到陌生,ECharts是一款基于javascript数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级项目
    Echarts官网链接: https://echarts.apache.org/zh/index.html

Echarts插件安装包
链接:https://pan.baidu.com/s/19399TOP_2i3GM-wR3Q71XA
提取码:kl66
解压后里面包含phantomjs-2.1.1-windows和echarts-convert.js,进入\echarts\phantomjs-2.1.1-windows\bin目录下通过cmd命令启动phantomjs D:\toos\echarts\saintlee-echartsconvert-master\echartsconvert\echarts-convert.js -s -p 6666

  1. 导入依赖
 <dependency>            <groupId>com.GitHub.abel533</groupId>            <artifactId>Echarts</artifactId>            <version>3.0.0.6</version>        </dependency>
  1. 直接上代码
    这里是echarts-pojo模块(数据模型)
@Datapublic class BarParam {    private Object[] barName;    private Object[] barValue;    private String legendName;}
@Datapublic class BarData {    private String title;  //标题    private BarParam barParamList;    private Boolean isHorizontal;  //是否水平放置    //省略get/set方法,使用lombok插件@Data}

对GsonOption.java做一层封装,继承GsonOption 类

 * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:13 **/@Datapublic class EnhancedOption extends GsonOption {    private String filepath;    private static boolean VIEW =false;    private static String EXPORT_PATH  ="";        public void print() {        GsonUtil.print(this);    }        public void printPretty() {        GsonUtil.printPretty(this);    }        public void view() {        if (!VIEW) {            return;        }        if (this.filepath != null) {            try {                OptionUtil.browse(this.filepath);            } catch (Exception e) {                this.filepath = OptionUtil.browse(this);            }        } else {            this.filepath = OptionUtil.browse(this);        }    }        public String exportTohtml(String fileName) {        return exportToHtml(EXPORT_PATH, fileName);    }}

请求工具类

@Slf4jpublic class HttpUtil {        public static String post(String url, Map<String, String> params, String charset)            throws ClientProtocolException, IOException {        log.info("httpPostRequest url : " + url + "   paramMap : " + params);        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();        //System.out.println("responseEntity = " + responseEntity);        return responseEntity;    }    public static String postUrl(String url, Map<String, Object> params, String charset) {        String responseEntity = "";        // 创建CloseableHttpClient对象        CloseableHttpClient client = HttpClients.createDefault();        // 创建post方式请求对象        HttpPost httpPost = new HttpPost(url);        // 将参数添加到post请求中        httpPost.setEntity(new StringEntity(JSONObject.toJSONString(params), charset));        // 发送请求,获取结果(同步阻塞)        CloseableHttpResponse response = null;        try {            response = client.execute(httpPost);            // 获取响应实体            HttpEntity entity = response.getEntity();            if (entity != null) {                // 按指定编码转换结果实体为String类型                responseEntity = EntityUtils.toString(entity, charset);            }            // 释放资源            EntityUtils.consume(entity);        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                response.close();            } catch (IOException e) {                e.printStackTrace();            }        }        return responseEntity;    }        public static String doPost(String url, String params) throws Exception {        log.info("httpPostRequest url : " + url + "   paramMap : " + params);        CloseableHttpClient httpclient = HttpClients.createDefault();        HttpPost httpPost = new HttpPost(url);// 创建httpPost        httpPost.setHeader("Accept", "application/json");        httpPost.setHeader("Content-Type", "application/json");        String charSet = "UTF-8";        StringEntity entity = new StringEntity(params, charSet);        //logger.info("entity = " + entity);        httpPost.setEntity(entity);        CloseableHttpResponse response = null;        try {            response = httpclient.execute(httpPost);            //logger.info("response = " + response);            StatusLine status = response.getStatusLine();            int state = status.getStatusCode();            if (state == HttpStatus.SC_OK) {                HttpEntity responseEntity = response.getEntity();                String jsonString = EntityUtils.toString(responseEntity);                log.info("post请求响应结果:{}", jsonString);                return jsonString;            }            else{                log.error("请求返回:"+state+"("+url+")");            }        }        finally {            if (response != null) {                try {                    response.close();                } catch (IOException e) {                    log.error(e.getMessage());                }            }            try {                httpclient.close();            } catch (IOException e) {                log.error(e.getMessage());            }        }        return null;    }        public static String doPostJson(String url, JSONObject paramsJson) {        log.info("httpPostRequest url : " + url + "   paramMap : " + paramsJson);        if(StringUtils.isBlank(url)){            log.error("httpPostRequest url is null");            return null;        }        String result = "";        try {            // 创建httpClient实例            CloseableHttpClient httpClient = HttpClients.createDefault();            // 创建httpPost远程连接实例            HttpPost httpPost = new HttpPost(url);            // 配置请求参数实例            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000)// 设置连接主机服务超时时间                    .setConnectionRequestTimeout(10000)// 设置连接请求超时时间                    .setSocketTimeout(30000)// 设置读取数据连接超时时间                    .build();            // 为httpPost实例设置配置            httpPost.setConfig(requestConfig);            // 设置请求头            httpPost.addHeader("content-type", "application/json;charset=utf-8");            // 封装post请求参数            httpPost.setEntity(new StringEntity(paramsJson.toJSONString(), Charset.forName("UTF-8")));            // httpClient对象执行post请求,并返回响应参数对象            //   HttpResponse httpResponse = httpClient.execute(httpPost);            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);            // 从响应对象中获取响应内容            result = EntityUtils.toString(httpResponse.getEntity());            //logger.info("result = {}" , result);        } catch (UnsupportedEncodingException e) {            log.error("URLUtil.httpPostRequest encounters an UnsupportedEncodingException : {}",e);        } catch (IOException e) {            log.error("URLUtil.httpPostRequest encounters an IOException : {}",e);        }        log.info("URLUtil.httpPostRequest -----result----: " + result);        return result;    }}**文件工具类**
public class FileUtil {    public static File generateImage(String base64, String path) throws IOException {        BASE64Decoder decoder = new BASE64Decoder();        File file = new File(path);        String fileName = file.getName();        System.out.println("file = " + file);        //创建临时文件        //File tempFile = File.createTempFile(fileName, ".png");        //FileOutputStream fos = new FileOutputStream(tempFile);*/        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();            return file;        }           }    public static void deleteFile(File file) {        //File file = new File();        String fileName = file.getName();        // 如果文件路径所对应的文件存在,并且是一个文件,则直接删除        if (file.exists() && file.isFile()) {            if (file.delete()) {                System.out.println("删除单个文件" + fileName + "成功!");            } else {                System.out.println("删除单个文件" + fileName + "失败!");            }        } else {            System.out.println("删除单个文件失败:" + fileName + "不存在!");        }    }}

EchartsUtil.java:将option转化为图片编码base64

public class EchartsUtil {//    private static String url = "http://localhost:6666";    private static final String SUCCESS_CODE = "1";    public static String generateEchartsBase64(String option, String url) 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 = JSONObject.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 GsonOption createBar(BarData barData){        String title = barData.getTitle();        boolean isHorizontal = barData.getIsHorizontal();        Object[] xdatas = barData.getBarParamList().getBarName();        Object[] ydatas = barData.getBarParamList().getBarValue();        String legendName = barData.getBarParamList().getLegendName();        Bar bar = new Bar();  //图类别(柱状图)        //title        EnhancedOption option = new EnhancedOption();        option.title(title);  //标题        option.title().textStyle().fontSize(15).color("#000000").fontWeight("bolder");        //工具栏 toolbox        option.toolbox().show(true).feature(Tool.mark,  //辅助线                Tool.dataView, //数据视图                new MagicType(Magic.line, Magic.bar), //线图,柱状图切换                Tool.restore, //还原                Tool.saveAsImage   //保存图片        );        option.toolbox().show(true).feature();        //tooltip        option.tooltip().show(true).formatter("{a}
{b} : {c}"
); //显示工具提示,设置提示格式 //legend Legend legend = new Legend(); TextStyle textStyle = new TextStyle(); textStyle.color("red"); textStyle.fontSize(10); textStyle.fontWeight("bolder"); legend.setData(Collections.singletonList(legendName)); legend.setTextStyle(textStyle);// legend.setBorderWidth(100); option.setLegend(legend); //图例 //axisLabel AxisLabel axisLabel = new AxisLabel(); TextStyle textStyle1 = new TextStyle(); textStyle1.fontSize(10); textStyle1.fontWeight("bolder"); axisLabel.show(true); axisLabel.textStyle(textStyle1); axisLabel.setRotate(40); axisLabel.setInterval(0); //axisLine AxisLine axisLine = new AxisLine(); LineStyle lineStyle = new LineStyle(); lineStyle.color("#000000"); lineStyle.width(4); axisLine.lineStyle(lineStyle); //xAxis CategoryAxis category = new CategoryAxis();// 轴分类 category.data(xdatas);// 轴数据类别 category.axisLabel(axisLabel); // x轴文字样式 category.axisLine(axisLine); //x轴样式 //yAxis ValueAxis valueAxis = new ValueAxis(); valueAxis.setName("次数"); valueAxis.axisLabel().show(true).textStyle().fontSize(15).fontWeight("bolder"); //y轴文字样式 valueAxis.axisLine().lineStyle().color("#315070").width(4); //y轴样式 //series bar.name(legendName); Normal normal = new Normal(); normal.setShow(true); if(barData.getIsHorizontal() == false){ normal.position(Position.inside); }else { normal.position(Position.top); } normal.color("green"); normal.textStyle().color("red").fontSize(15).fontWeight("bolder"); bar.setBarWidth("70"); //柱条宽度// bar.setBarMaxWidth(100); //柱条最大宽度 //bar.setBarMinHeight(10); //柱条最小高度 bar.label().normal(normal); //循环数据 for(int i = 0;i < xdatas.length;i++){ int data = (int) ydatas[i]; String color = "rgb(251,153,2)"; //类目对应的柱状图 Map<String, Object> map = new HashMap<>(2); map.put("value", data); map.put("itemStyle", new ItemStyle().normal(new Normal().color(color))); bar.data(map); } if(isHorizontal){ //横轴为类别,纵轴为值 option.xAxis(category); //x轴 option.yAxis(valueAxis); //y轴 }else { //横轴为值,纵轴为类别 option.xAxis(valueAxis); //x轴 option.yAxis(category); //y轴 } option.series(bar); return option; }
  1. 启动测试
@Slf4jpublic class EchartBar {    private static   String  requestUrl= "http://127.0.0.1:6666";    private static   String  imgUrl= "F:/";    public static void main(String[] args) {        BarData barData = new BarData();        barData.setTitle("Test");        barData.setIsHorizontal(true);        BarParam barParam = new BarParam();        String[] columnKeys = {"Test1","Test2","Test3","Test4","Test5","Test6","Test7"};        barParam.setBarName(columnKeys);        Object[] data ={1,9,0,15,9,3,4};        barParam.setBarValue(data);        barData.setBarParamList(barParam);        GsonOption option = createBar(barData);        String optionStr = JSONObject.toJSONString(option);        log.error(optionStr);        if(optionStr == null || "".equals(optionStr)){            return;        }        try {            String base64 =  EchartsUtil.generateEchartsBase64(optionStr, requestUrl);            log.info("base64:" + base64);            long nowStr = Calendar.getInstance().getTimeInMillis();            //图片名            String imageName =  JDate.getDuanshijian(new JDate(),"yyyy-MM-dd_HH_mm_ss") +".png";            log.info("bar图片:" + imageName);            File oldfile = FileUtil.generateImage(base64, imgUrl+imageName);        } catch (Exception e) {            e.printStackTrace();        }    }
  • 生成图片展示
    在这里插入图片描述

两种方案到这就都实现了,来讲一下这两种的优缺点吧

  • JFreeChart 方便快捷,不需要自己去安装启动什么服务,而Echarts插件需要安装启动一个服务
  • JFreeChart 生成的图片清晰度感觉不是很清晰,Echarts的X轴字符太多导致展示不齐全

以上是个人觉得,不诋毁。可能是我没有细去研究,有知道解决方案的可以指导一下,上面有什么地方不懂的可以评论,看到必回的,让兄弟们不要在里面碰壁。

来源地址:https://blog.csdn.net/weixin_55518591/article/details/130678710

--结束END--

本文标题: Java生成Echarts表图的两种方案

本文链接: https://lsjlt.com/news/400463.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作