需求:
后端根据数据自动生成2个图片,然后把两张图片合并成一张图片,再发到钉钉群里,涉及到定时生成和推送,当时我们测试同事说他们写定时脚本放到服务器上,然后让我提供生成图片的方法和钉钉机器人的逻辑
天下文字一大抄,集各位大佬精华,最后成果如下

依赖
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.6.6</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.example</groupId>
- <artifactId>demo</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>imagedemo</name>
- <description>Demo project for Spring Boot</description>
- <properties>
- <java.version>8</java.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- <!--柱状图制作引入-->
- <dependency>
- <groupId>org.jfree</groupId>
- <artifactId>jfreechart</artifactId>
- <version>1.0.19</version>
- </dependency>
-
- <!--oss引入-->
- <dependency>
- <groupId>com.aliyun.oss</groupId>
- <artifactId>aliyun-sdk-oss</artifactId>
- <version>3.15.1</version>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.22</version>
- </dependency>
-
- <!--钉钉机器人引入-->
- <dependency>
- <groupId>com.aliyun</groupId>
- <artifactId>alibaba-dingtalk-service-sdk</artifactId>
- <version>2.0.0</version>
- </dependency>
-
- <!--常用工具类-->
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.8.20</version>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- </project>
配置
- server:
- port: 9111
-
- #oss配置
- aliyun:
- oss:
- enable: true
- name: alioss
- accessKey: xxx
- secretKey: xxx
- bucketName: xxx
- endpoint: xxx
- pathPrefix: xxx #生成图片所在的文件夹
- #钉钉机器人
- sys:
- pe:
- dingtalk:
- robotMsgUrl: xxxurl
- secret: xxx
配置类
- package com.example.demo.config;
-
-
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
-
- @Data
- @Component
- @ConfigurationProperties(prefix = "sys.pe.dingtalk")
- public class DingTalkConfig {
- private String robotMsgUrl; //系统预警机器人推送群地址
- private String secret; //系统预警机器人推送群地址
- }
- package com.example.demo.config;
-
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
-
- @Data
- @Component
- @ConfigurationProperties(prefix = "aliyun.oss")
- public class OssConfig {
-
- private String endpoint;
-
- private String accessKey;
-
- private String secretKey;
-
- private String bucketName; //桶名称
-
- private String pathPrefix; //生成文件路径前缀
-
- }
module【除serie外,另外一个根据自己需求自行确定是否要用】
- package com.example.demo.model;
-
- import java.io.Serializable;
- import java.util.Vector;
-
- /**
- * @author zsl0
- * created on 2023/7/6 17:51
- */
- public class Serie implements Serializable {
-
- private static final long serialVersionUID = 1L;
- private String name;// 名字
- private Vector
-
- public Serie() {
-
- }
-
- /**
- *
- * @param name
- * 名称(线条名称)
- * @param data
- * 数据(线条上的所有数据值)
- */
- public Serie(String name, Vector {
-
- this.name = name;
- this.data = data;
- }
-
- /**
- *
- * @param name
- * 名称(线条名称)
- * @param array
- * 数据(线条上的所有数据值)
- */
- public Serie(String name, Object[] array) {
- this.name = name;
- if (array != null) {
- data = new Vector
- for (int i = 0; i < array.length; i++) {
- data.add(array[i]);
- }
- }
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Vector
- return data;
- }
-
- public void setData(Vector {
- this.data = data;
- }
-
- }
-
- package com.example.demo.model;
-
- import lombok.AllArgsConstructor;
- import lombok.Builder;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- @Data
- @AllArgsConstructor
- @NoArgsConstructor
- @Builder
- public class SystemApiCount {
- private String systemName;
- private Integer count;
- }
生成图片util
- package com.example.demo.utils;
-
- import com.example.demo.model.Serie;
- import lombok.extern.slf4j.Slf4j;
- import org.jfree.chart.ChartFactory;
- import org.jfree.chart.StandardChartTheme;
- import org.jfree.chart.axis.CategoryAxis;
- import org.jfree.chart.axis.NumberAxis;
- import org.jfree.chart.axis.ValueAxis;
- import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
- import org.jfree.chart.plot.CategoryPlot;
- import org.jfree.chart.plot.DefaultDrawingSupplier;
- import org.jfree.chart.plot.PieLabelLinkStyle;
- import org.jfree.chart.renderer.category.BarRenderer;
- import org.jfree.chart.renderer.category.StandardBarPainter;
- import org.jfree.chart.renderer.xy.StandardXYBarPainter;
- import org.jfree.data.category.DefaultCategoryDataset;
- import org.jfree.ui.RectangleInsets;
-
- import java.awt.*;
- import java.util.Vector;
-
- /**
- * Jfreechart工具类
- *
- * 解决中午乱码问题
- * 用来创建类别图表数据集、创建饼图数据集、时间序列图数据集
- * 用来对柱状图、折线图、饼图、堆积柱状图、时间序列图的样式进行渲染
- * 设置X-Y坐标轴样式
- *
- *
- * @author chenchangwen
- * @since:2014-2-18
- */
- @Slf4j
- public class ChartUtil {
- private static String NO_DATA_MSG = "数据加载失败";
- private static Font FONT = new Font("宋体", Font.PLAIN, 12);
- // public static Color[] CHART_COLORS = {
- // new Color(22, 102, 149), new Color(92, 92, 97), new Color(144, 237, 125), new Color(255, 188, 117),
- // new Color(60, 142, 116), new Color(255, 117, 153), new Color(253, 236, 109), new Color(128, 133, 232),
- // new Color(43, 66, 147), new Color(255, 204, 102)};// 颜色
-
- public static Color[] CHART_COLORS = {
- new Color(12, 250, 194, 195), new Color(16, 161, 246), new Color(22, 102, 149)};// 颜色
-
- static {
- setChartTheme();
- }
-
- public ChartUtil() {
- }
-
- /**
- * 中文主题样式 解决乱码
- */
- private static void setChartTheme() {
- // 设置中文主题样式 解决乱码
- StandardChartTheme chartTheme = new StandardChartTheme("CN");
- // 设置标题字体
- chartTheme.setExtraLargeFont(FONT);
- // 设置图例的字体
- chartTheme.setRegularFont(FONT);
- // 设置轴向的字体
- chartTheme.setLargeFont(FONT);
- chartTheme.setSmallFont(FONT);
- chartTheme.setTitlePaint(new Color(51, 51, 51));
- chartTheme.setSubtitlePaint(new Color(85, 85, 85));
-
- chartTheme.setLegendBackgroundPaint(Color.WHITE);// 设置标注
- chartTheme.setLegendItemPaint(Color.BLACK);//
- chartTheme.setChartBackgroundPaint(Color.WHITE);
- // 绘制颜色绘制颜色.轮廓供应商
- // paintSequence,outlinePaintSequence,strokeSequence,outlineStrokeSequence,shapeSequence
-
- Paint[] OUTLINE_PAINT_SEQUENCE = new Paint[]{Color.WHITE};
- // 绘制器颜色源
- DefaultDrawingSupplier drawingSupplier = new DefaultDrawingSupplier(CHART_COLORS, CHART_COLORS, OUTLINE_PAINT_SEQUENCE,
- DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE, DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
- DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE);
- chartTheme.setDrawingSupplier(drawingSupplier);
-
- chartTheme.setPlotBackgroundPaint(Color.WHITE);// 绘制区域
- chartTheme.setPlotOutlinePaint(Color.WHITE);// 绘制区域外边框
- chartTheme.setLabelLinkPaint(new Color(8, 55, 114));// 链接标签颜色
- chartTheme.setLabelLinkStyle(PieLabelLinkStyle.CUBIC_CURVE);
-
- chartTheme.setAxisOffset(new RectangleInsets(5, 12, 5, 12));
- chartTheme.setDomainGridlinePaint(new Color(192, 208, 224));// X坐标轴垂直网格颜色
- chartTheme.setRangeGridlinePaint(new Color(192, 192, 192));// Y坐标轴水平网格颜色
-
- chartTheme.setBaselinePaint(Color.WHITE);
- chartTheme.setCrosshairPaint(Color.BLUE);// 不确定含义
- chartTheme.setAxisLabelPaint(new Color(51, 51, 51));// 坐标轴标题文字颜色
- chartTheme.setTickLabelPaint(new Color(67, 67, 72));// 刻度数字
- chartTheme.setBarPainter(new StandardBarPainter());// 设置柱状图渲染
- chartTheme.setXYBarPainter(new StandardXYBarPainter());// XYBar 渲染
-
- chartTheme.setItemLabelPaint(Color.black);
- chartTheme.setThermometerPaint(Color.white);// 温度计
-
- ChartFactory.setChartTheme(chartTheme);
- }
-
- /**
- * 创建类别数据集合
- */
- public static DefaultCategoryDataset createDefaultCategoryDataset(Vector
series, String[] categories) { - DefaultCategoryDataset dataset = new DefaultCategoryDataset();
-
- for (Serie serie : series) {
- String name = serie.getName();
- Vector
- if (data != null && categories != null && data.size() == categories.length) {
- for (int index = 0; index < data.size(); index++) {
- String value = data.get(index) == null ? "" : data.get(index).toString();
- if (isPercent(value)) {
- value = value.substring(0, value.length() - 1);
- }
- if (isNumber(value)) {
- dataset.setValue(Double.parseDouble(value), name, categories[index]);
- }
- }
- }
-
- }
- return dataset;
- }
-
- /**
- * 设置柱状图渲染
- *
- * @param plot 绘图
- * @param isShowDataLabels
- */
- public static void setBarRenderer(CategoryPlot plot, boolean isShowDataLabels) {
-
- plot.setNoDataMessage(NO_DATA_MSG);
- plot.setInsets(new RectangleInsets(10, 20, 5, 20));
-
- // 设置柱状图样式
- BarRenderer renderer = (BarRenderer) plot.getRenderer();
- renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
- //设置每个柱子之间的距离【柱子之间的距离和柱子的最大宽度以及你生成的图片的宽度,这三个参数应该挺有关系会影响展示】
- renderer.setItemMargin(-3);
- renderer.setMaximumBarWidth(0.015);// 设置柱子最大宽度
- for (int i = 0; i < CHART_COLORS.length; i++) {
- // 设置柱子颜色
- renderer.setSeriesPaint(i, CHART_COLORS[i]);
- }
-
- renderer.setShadowVisible(false); // 去除阴影效果
-
- // 设置轴样式jf
- CategoryAxis domainAxis = plot.getDomainAxis();
- domainAxis.setTickLabelFont(new Font("宋体", Font.PLAIN, 14)); // 设置X轴上提示文字样式
- domainAxis.setLabelFont(new Font("宋体", Font.PLAIN, 15)); // 设置X轴下的标签文字
- domainAxis.setTickLabelInsets(new RectangleInsets(10, 20, 5, 20));
- // domainAxis.setTickMarksVisible(false); // 坐标轴标尺不显示
- // domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45); //X轴刻度倾斜45度
-
- NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
- rangeAxis.setTickLabelFont(new Font("宋体", Font.PLAIN, 14)); // 设置Y轴的提示文字样式
- rangeAxis.setLabelFont(new Font("宋体", Font.PLAIN, 15));
- rangeAxis.setTickLabelsVisible(false); //y轴数值不显示
-
- plot.setRangeGridlinesVisible(false); //数据轴网格不显示
- // rangeAxis.setLowerMargin(0.35); // 设置最低的一个 Item 与图片底端的距离
- // rangeAxis.setUpperMargin(0.45); // 设置最高的一个 Item 与图片顶端的距离
- // rangeAxis.setUpperBound(8000.0); // 设置Y轴的最大值
-
-
- if (isShowDataLabels) {
- renderer.setBaseItemLabelsVisible(true);
- }
-
- setXAixs(plot);
- setYAixs(plot);
- }
-
- /**
- * 设置类别图表(CategoryPlot) X坐标轴线条颜色和样式
- *
- * @param plot 绘图
- */
- private static void setXAixs(CategoryPlot plot) {
- Color lineColor = new Color(31, 121, 170);
- plot.getDomainAxis().setAxisLinePaint(lineColor);// X坐标轴颜色
- plot.getDomainAxis().setTickMarkPaint(lineColor);// X坐标轴标记|竖线颜色
-
- }
-
- /**
- * 设置类别图表(CategoryPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示
- *
- * @param plot 绘图
- */
- private static void setYAixs(CategoryPlot plot) {
- Color lineColor = new Color(192, 208, 224);
- ValueAxis axis = plot.getRangeAxis();
- axis.setAxisLinePaint(lineColor);// Y坐标轴颜色
- axis.setTickMarkPaint(lineColor);// Y坐标轴标记|竖线颜色
- // 隐藏Y刻度
- axis.setAxisLineVisible(false);
- axis.setTickMarksVisible(false);
- // Y轴网格线条
- plot.setRangeGridlinePaint(new Color(192, 192, 192));
- plot.setRangeGridlineStroke(new BasicStroke(1));
-
- plot.getRangeAxis().setUpperMargin(0.1);// 设置顶部Y坐标轴间距,防止数据无法显示
- plot.getRangeAxis().setLowerMargin(0.1);// 设置底部Y坐标轴间距
-
- }
-
- /**
- * 是不是一个%形式的百分比
- *
- * @param str
- * @return
- */
- private static boolean isPercent(String str) {
- return str != null ? str.endsWith("%") && isNumber(str.substring(0, str.length() - 1)) : false;
- }
-
- /**
- * 是不是一个数字
- *
- * @param str
- * @return
- */
- private static boolean isNumber(String str) {
- return str != null ? str.matches("^[-+]?(([0-9]+)((([.]{0})([0-9]*))|(([.]{1})([0-9]+))))$") : false;
- }
-
-
- }
阿里云oss上传util
- package com.example.demo.utils;
-
- import cn.hutool.core.date.DatePattern;
- import cn.hutool.core.date.DateUtil;
- import com.aliyun.oss.OSS;
- import com.aliyun.oss.OSSClientBuilder;
- import com.example.demo.config.OssConfig;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.context.annotation.Configuration;
-
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.URL;
- import java.util.Date;
- import java.util.UUID;
-
- @Slf4j
- @Configuration
- public class OssUploadUtil {
-
-
- public static String uploadImage(String filPath, OssConfig ossConfig) throws IOException {
- OSS ossClient = null;
- InputStream inputStream = null;
- try {
- // 创建OSSClient实例。
- ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKey(), ossConfig.getSecretKey());
- //生成任意文件名称
- UUID uuid = UUID.randomUUID();
- String imagePath = ossConfig.getPathPrefix() + "/" + DateUtil.format(new Date(System.currentTimeMillis()), DatePattern.NORM_DATE_PATTERN) + "/" + uuid + ".png";
- // 数据流
- inputStream = new FileInputStream(filPath);
- // 填写Bucket名称和Object完整路径。Object完整路径中不能包含Bucket名称。
- ossClient.putObject(ossConfig.getBucketName(), imagePath, inputStream);
- String key = imagePath;
- System.out.println("imagePath = " + imagePath);
- //因为申请公司内的阿里云oss桶的时候,oss生成的图片所在的文件夹权限继承于桶,那么生成这个链接之后就不能被公网访问,当时公司要求文件夹权限或图片权限不能改成公共读,所以就采用了生成的url链接拼接有效期的形式
- Date expiration = new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365); //设置从此刻开始一年有效
- URL url = ossClient.generatePresignedUrl(ossConfig.getBucketName(), key, expiration);
- return url.toString();
- } catch (Exception e) {
- log.error("sso upload error", e);
- } finally {
- // 关闭OSSClient和数据流【一定要关闭,否则会失败】
- if (ossClient != null) ossClient.shutdown();
- if (inputStream != null) inputStream.close();
- }
- return "";
- }
-
- }
钉钉机器人uitl
- package com.example.demo.utils;
-
- import com.dingtalk.api.DefaultDingTalkClient;
- import com.dingtalk.api.DingTalkClient;
- import com.dingtalk.api.request.OapiRobotSendRequest;
- import com.dingtalk.api.response.OapiRobotSendResponse;
- import com.example.demo.config.DingTalkConfig;
- import com.taobao.api.ApiException;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.codec.binary.Base64;
-
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import java.net.URLEncoder;
-
- @Slf4j
- public class DingTalkUtil {
-
- /**
- * 图片语法
- *
- * @param phone
- */
- public static void sendRobotMessage(String phone, String imageUrl, DingTalkConfig dingTalkConfig) throws Exception {
- try {
- Long timestamp = System.currentTimeMillis();
- String sign = getSign(dingTalkConfig.getSecret(), timestamp);
-
- DingTalkClient client = new DefaultDingTalkClient(dingTalkConfig.getRobotMsgUrl() + "&sign=" + sign + "×tamp=" + timestamp);
-
- OapiRobotSendRequest request = new OapiRobotSendRequest();
- request.setMsgtype("markdown");
- OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
- markdown.setTitle("测试图片");
- // markdown.setText(" @" + phone + " \n " +
- // "");
- markdown.setText("");
- request.setMarkdown(markdown);
- //@全体,如果要@单独几个人再去看钉钉机器人推送相关文档
- OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
- // at.setAtUserIds(Arrays.asList(userId));
- // isAtAll类型如果不为Boolean,请升级至最新SDK
- at.setIsAtAll(Boolean.TRUE);
- request.setAt(at);
- OapiRobotSendResponse response = client.execute(request);
- System.out.println(response.getBody());
- } catch (ApiException e) {
- e.printStackTrace();
- }
- }
-
- //钉钉机器人推送设置加签方式推送
- public static String getSign(String secret, Long timestamp) throws Exception {
- String stringToSign = timestamp + "\n" + secret;
- Mac mac = Mac.getInstance("HmacSHA256");
- mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
- byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
- String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
- return sign;
- }
- }
图片合并util
- package com.example.demo.utils;
-
- import javax.imageio.ImageIO;
- import java.awt.*;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.io.IOException;
-
- public class ImageConnectUtil {
-
- //图片垂直合并
- public static void connectImageWidthVertical(String topImagePath, String bottomImagePath, String targetImagePath) throws IOException {
- BufferedImage topBufImage = ImageIO.read(new File(topImagePath));
- BufferedImage bottomBufImage = ImageIO.read(new File(bottomImagePath));
-
- int connImageWidth = Math.max(topBufImage.getWidth(), bottomBufImage.getHeight()); //目标图片宽度
- int connImageHeight = topBufImage.getHeight() + bottomBufImage.getHeight() + 40; //目标图片高度=第一个图片高度+第二个图片高度+两个图片之间间距
-
- BufferedImage connImage = new BufferedImage(connImageWidth, connImageHeight, BufferedImage.TYPE_INT_RGB);
- Graphics connGraphics = connImage.getGraphics();
- connGraphics.fillRect(0, 0, connImageWidth, connImageHeight); //设置目标图片底部为白色
- connGraphics.setColor(Color.white);
- //第一张图左上角坐标为(0, 0)
- connGraphics.drawImage(topBufImage, 0, 0, null);
- connGraphics.drawImage(bottomBufImage, 0, topBufImage.getHeight() + 40, null); //第二张图片在第一章图片40px高的位置下边
-
- String targetFileName = targetImagePath.split("\\.")[1];
- ImageIO.write(connImage, targetFileName, new File(targetImagePath));
- }
-
- }
-
测试类
- package com.example.demo;
-
- import cn.hutool.core.date.DatePattern;
- import cn.hutool.core.date.DateUtil;
- import com.example.demo.config.DingTalkConfig;
- import com.example.demo.config.OssConfig;
- import com.example.demo.model.Serie;
- import com.example.demo.model.SystemApiCount;
- import com.example.demo.utils.ChartUtil;
- import com.example.demo.utils.DingTalkUtil;
- import com.example.demo.utils.ImageConnectUtil;
- import com.example.demo.utils.OssUploadUtil;
- import org.jfree.chart.ChartFactory;
- import org.jfree.chart.ChartUtilities;
- import org.jfree.chart.JFreeChart;
- import org.jfree.chart.block.BlockBorder;
- import org.jfree.chart.plot.CategoryPlot;
- import org.jfree.chart.plot.PlotOrientation;
- import org.jfree.chart.title.TextTitle;
- import org.jfree.data.category.DefaultCategoryDataset;
- import org.jfree.ui.RectangleEdge;
- import org.jfree.ui.RectangleInsets;
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
-
- import java.awt.*;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.List;
- import java.util.*;
- import java.util.stream.Collectors;
-
-
- @SpringBootTest
- public class TestImageJF {
-
- @Autowired
- private DingTalkConfig dingTalkConfig;
-
- @Autowired
- private OssConfig ossConfig;
-
- @Test
- public void testCreateImage() throws Exception {
- String fileName1 = UUID.randomUUID().toString();
- //创建image文件夹
- String dirPath = createFolder("image") + File.separator + fileName1 + ".png";
- System.out.println("dirPath = " + dirPath);
- //获取创建的图片地址1
- createImage(dirPath);
- //获取创建的图片地址2
- String dirPath2 = createFolder("image") + File.separator + fileName1 + ".png";
- createImage(dirPath2);
- //合并图片1和图片2
- String dirPath3 = createFolder("image") + File.separator + fileName1 + ".png";
- ImageConnectUtil.connectImageWidthVertical(dirPath, dirPath2, dirPath3);
- //sso上传图片,获得公网下的图片url
- String uploadUrl = OssUploadUtil.uploadImage(dirPath3, ossConfig);
- System.out.println("uploadUrl = " + uploadUrl);
- //钉钉上传图片
-
- //钉钉机器人发送图片消息
- String phone = "19890909090";
- DingTalkUtil.sendRobotMessage(phone, uploadUrl, dingTalkConfig);
- //删除在项目中生成的图片
- deleteFile(dirPath);
- deleteFile(dirPath2);
- deleteFile(dirPath3);
- }
-
-
- //生成image文件夹
- public String createFolder(String folderName) {
- String path = System.getProperty("user.dir");
- //create folder
- String dirPath = path + File.separator + folderName;
- File dir = new File(dirPath);
- dir.mkdirs();
- return dirPath;
- }
-
- //删除图片
- private void deleteFile(String filePath) {
- File file = new File(filePath);
- if (file.isFile() && file.exists()) {
- boolean delete = file.delete();
- System.out.println("delete = " + delete);
- }
- }
-
-
- public void createImage(String fileLocation) throws IOException {
- FileOutputStream fileOutputStream = null;
- try {
- //获取所有系统的接口数量
- List
systemApiCounts = new ArrayList<>(); - int count = 900;
- String prefix = "xx中心";
- for (int i = 0; i < 16; i++) {
- systemApiCounts.add(SystemApiCount.builder().systemName(prefix + i).count(count).build());
- count -= 50;
- }
-
-
- //获取所有系统的执行用例数
- List
systemUseCaseExecCounts = new ArrayList<>(); - int useCaseCount = 900;
- for (int i = 0; i < 16; i++) {
- systemUseCaseExecCounts.add(SystemApiCount.builder().systemName(prefix + i).count(useCaseCount).build());
- useCaseCount -= 50;
-
- }
-
- //获取所有系统的失败用例数
- List
failUseCaseExecCounts = new ArrayList<>(); - int failedUseCaseCount = 900;
- for (int i = 0; i < 16; i++) {
- failUseCaseExecCounts.add(SystemApiCount.builder().systemName(prefix + i).count(failedUseCaseCount).build());
- failedUseCaseCount -= 50;
- }
-
- // // 创建数据系列
- List
systemName = systemApiCounts.stream().map(SystemApiCount::getSystemName).filter(Objects::nonNull).distinct().collect(Collectors.toList()); -
- //数据分别根据中心排序
- List
apiCounts = systemApiCounts.stream() - .sorted(Comparator.comparing(item -> systemName.indexOf(item.getSystemName()))).map(SystemApiCount::getCount).collect(Collectors.toList());
- List
useCaseExecCounts = systemUseCaseExecCounts.stream() - .sorted(Comparator.comparing(item -> systemName.indexOf(item.getSystemName()))).map(SystemApiCount::getCount).collect(Collectors.toList());
- List
failUseCaseExecCountList = failUseCaseExecCounts.stream() - .sorted(Comparator.comparing(item -> systemName.indexOf(item.getSystemName()))).map(SystemApiCount::getCount).collect(Collectors.toList());
-
- Serie serie1 = new Serie("调用接口数", new Vector<>(apiCounts));
- Serie serie2 = new Serie("超时接口数", new Vector<>(useCaseExecCounts));
- Serie serie3 = new Serie("失败接口数", new Vector<>(failUseCaseExecCountList));
-
- // 创建数据集
- DefaultCategoryDataset dataset = ChartUtil.createDefaultCategoryDataset(new Vector<>(Arrays.asList(serie1, serie2, serie3)),
- systemName.toArray(new String[systemName.size()]));
- // 创建柱状图
- String title = DateUtil.format(new Date(System.currentTimeMillis()), DatePattern.CHINESE_DATE_PATTERN) + "系统接入接口监控情况";
- JFreeChart chart = ChartFactory.createBarChart(
- title, // 图表标题
- "", // X轴标题
- "", // Y轴标题
- dataset, // 数据集
- PlotOrientation.VERTICAL,// 图表方向
- // PlotOrientation.HORIZONTAL,// 图表方向
- true, // 是否显示图例
- true, // 是否生成工具提示
- false // 是否生成URL链接
- );
-
- chart.setTitle(new TextTitle(title, new Font("宋体", Font.BOLD, 20)));
- chart.getTitle().setMargin(18, 0, 0, 0);
- chart.getTitle().setPaint(Color.GREEN);
- chart.getLegend().setFrame(new BlockBorder(Color.WHITE));
- chart.getLegend().setPosition(RectangleEdge.TOP);//设置图例在顶部
- chart.getLegend().setItemFont(new Font("宋体", Font.PLAIN, 14)); //设置图例大小
- chart.getLegend().setItemLabelPadding(new RectangleInsets(2, 2, 2, 2)); //设置图例位置
- chart.getLegend().setMargin(18, 0, 0, 0); //这样就只是距离右边有距离 margin 18
- chart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
- chart.setBorderVisible(true); //设置图片边框显示
- chart.setBorderPaint(Color.BLACK); //图片边框颜色
-
- // StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
- // //创建主题样式
- // //设置标题字体
- // standardChartTheme.setExtraLargeFont(new Font("隶书", Font.BOLD, 20));
- // //设置图例的字体
- // standardChartTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
- // //设置轴向的字体
- // standardChartTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
- // //应用主题样式
- // ChartFactory.setChartTheme(standardChartTheme);
-
-
- // 对柱状图进行样式渲染
- CategoryPlot plot = chart.getCategoryPlot();
- ChartUtil.setBarRenderer(plot, true);
- fileOutputStream = new FileOutputStream(fileLocation);
- //如果后续有其他中心接入,数据增多的情况下可把宽高设置大点
- ChartUtilities.writeChartAsJPEG(fileOutputStream, 1.0f, chart,
- 1850, 650, null);// 输出图表
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (fileOutputStream != null) {
- fileOutputStream.close();
- }
- }
-
- }
-
- }