java实现钉钉机器人消息推送
项目开发中需要用到钉钉机器人发送任务状态,本来想单独做一个功能就好,但是想着公司用到钉钉机器人发送项目挺多的。所以把这个钉钉机器人抽离成一个组件发布到企业maven仓库,这样可以给其他同事用提高工作效率。
1.目录结构

2.用抽象类(abstract)规范钉钉发送消息模版
2.1创建一个抽象类
public abstract class BaseMessage {public BaseMessage() {initMsg();}protected String msgType;public String getMsgType() {return msgType;}protected abstract void initMsg();/*** 返回Message对象组装出来的Map对象,供后续JSON序列化** @return Map*/public abstract JSONObject toMessageMap();
}
2.2钉钉(link,text,markdown)类型创建实体继承BaseMessgae
钉钉api文档 添加链接描述
LinkMessage类
@Data
public class LinkMessage extends BaseMessage {/*** 消息简介*/private String text;/*** 消息标题*/private String title;/*** 封面图片URL*/private String picUrl;/*** 消息跳转URL*/private String messageUrl;public LinkMessage() {}public LinkMessage(String title, String text, String messageUrl) {this.text = text;this.title = title;this.messageUrl = messageUrl;}public LinkMessage(String title, String text, String messageUrl, String picUrl) {this.text = text;this.title = title;this.picUrl = picUrl;this.messageUrl = messageUrl;}@Overrideprotected void initMsg() {this.msgType = DingTalkMsgEnum.LINK.getType();}@Overridepublic JSONObject toMessageMap() {if (StringUtils.isEmpty(this.text) || !DingTalkMsgEnum.LINK.getType().equals(this.msgType)) {throw new IllegalArgumentException("please check the necessary parameters!");}JSONObject resultMap = JSONUtil.createObj();resultMap.put("msgtype", this.msgType);JSONObject linkItems = JSONUtil.createObj();linkItems.put("title", this.title);linkItems.put("text", this.text);linkItems.put("picUrl", this.picUrl);linkItems.put("messageUrl", this.messageUrl);resultMap.put("link", linkItems);return resultMap;}
}TextMessage 类
@Data
public class TextMessage extends BaseMessage {/*** 文本消息的具体内容*/private String content;/*** 可以通过群成员的绑定手机号来艾特具体的群成员*/private String[] atMobiles;/*** 是否艾特所有人* 也可以设置isAtAll=true来艾特所有人*/private boolean isAtAll;public TextMessage() {}public TextMessage(String content) {this.content = content;}public TextMessage(String content, String[] atMobiles) {this.content = content;this.atMobiles = atMobiles;}public TextMessage(String content, boolean isAtAll) {this.content = content;this.isAtAll = isAtAll;}@Overrideprotected void initMsg() {this.msgType = DingTalkMsgEnum.TEXT.getType();}@Overridepublic JSONObject toMessageMap() {if (StringUtils.isEmpty(this.content) || !DingTalkMsgEnum.TEXT.getType().equals(this.msgType)) {throw new IllegalArgumentException("please check the necessary parameters!");}JSONObject resultMap = JSONUtil.createObj();resultMap.put("msgtype", this.msgType);JSONObject textItems = JSONUtil.createObj();textItems.put("content", this.content);resultMap.put("text", textItems);JSONObject atItems = JSONUtil.createObj();atItems.put("atMobiles", this.atMobiles);atItems.put("isAtAll", this.isAtAll);resultMap.put("at", atItems);return resultMap;}
}MarkdownMessage
@Data
public class MarkdownMessage extends BaseMessage {/*** 消息简介*/private String text;/*** 消息标题*/private String title;/*** 可以通过群成员的绑定手机号来艾特具体的群成员*/private String[] atMobiles;/*** 是否艾特所有人* 也可以设置isAtAll=true来艾特所有人*/private boolean isAtAll;public MarkdownMessage() {}public MarkdownMessage(String title, String text) {this.text = text;this.title = title;}public MarkdownMessage(String title, String text, String[] atMobiles) {this.text = text;this.title = title;this.atMobiles = atMobiles;}public MarkdownMessage(String title, String text, boolean isAtAll) {this.text = text;this.title = title;this.isAtAll = isAtAll;}@Overrideprotected void initMsg() {this.msgType = DingTalkMsgEnum.MARKDOWN.getType();}@Overridepublic JSONObject toMessageMap() {if (StringUtils.isEmpty(this.text) || !DingTalkMsgEnum.MARKDOWN.getType().equals(this.msgType)) {throw new IllegalArgumentException("please check the necessary parameters!");}JSONObject resultMap = JSONUtil.createObj();resultMap.put("msgtype", this.msgType);JSONObject markdownItems = JSONUtil.createObj();markdownItems.put("title", this.title);markdownItems.put("text", this.text);resultMap.put("markdown", markdownItems);JSONObject atItems = JSONUtil.createObj();atItems.put("atMobiles", this.atMobiles);atItems.put("isAtAll", this.isAtAll);resultMap.put("at", atItems);return resultMap;}
}
3. 钉钉异常错误类
public class DingTalkResponse {/*** 错误码*/private Integer errcode;/*** 错误信息*/private String errmsg;public Integer getErrcode() {return errcode;}public void setErrcode(Integer errcode) {this.errcode = errcode;}public String getErrmsg() {return errmsg;}public void setErrmsg(String errmsg) {this.errmsg = errmsg;}@Overridepublic String toString() {return "DingTalkResponse{" +"errcode=" + errcode +", errmsg='" + errmsg + '\'' +'}';}
}
4.钉钉类型枚举
@Getter
public enum DingTalkMsgEnum {LINK("link"),TEXT("text"),MARKDOWN("markdown");private final String type;DingTalkMsgEnum(String type) {this.type = type;}}
5.实现类方法
public class DingTalkRobotClient {/*** 钉钉机器人WebHook地址的access_token*/private String accessToken;private static String DING_TALK_PATH = "https://oapi.dingtalk.com/robot/send?access_token=ACCESS_TOKEN";public DingTalkRobotClient(String token) {if(StringUtils.isEmpty(token)){throw new ServiceException("accessToken获取失败!");}this.accessToken = token;}private DingTalkResponse sendMessage(BaseMessage message) {String result = HttpUtil.post(DING_TALK_PATH.replace("ACCESS_TOKEN", this.accessToken), message.toMessageMap().toString());DingTalkResponse dingTalkResponse = JSON.parseObject(result, DingTalkResponse.class);// 对DingTalkResponse为空情况做异常封装if (dingTalkResponse == null) {throw new ServiceException("请求钉钉报错!");}if (dingTalkResponse.getErrcode() != 0) {throw new ServiceException(String.format("错误码:%s;%s", dingTalkResponse.getErrcode(), dingTalkResponse.getErrmsg()));}return dingTalkResponse;}/*** 发送文本消息到钉钉** @param message* @return*/public DingTalkResponse sendTextMessage(TextMessage message) {return this.sendMessage(message);}/*** 发送文本消息到钉钉** @param content* @return*/public DingTalkResponse sendTextMessage(String content) {return this.sendMessage(new TextMessage(content));}/*** 发送文本消息到钉钉** @param content* @param atMobiles* @return*/public DingTalkResponse sendTextMessage(String content, String[] atMobiles) {return this.sendMessage(new TextMessage(content, atMobiles));}/*** 发送文本消息到钉钉** @param content* @param isAtAll* @return*/public DingTalkResponse sendTextMessage(String content, boolean isAtAll) {return this.sendMessage(new TextMessage(content, isAtAll));}/*** 发送Link消息到钉钉** @param message* @return*/public DingTalkResponse sendLinkMessage(LinkMessage message) {return this.sendMessage(message);}/*** 发送Link消息到钉钉** @param title* @param text* @param messageUrl* @return*/public DingTalkResponse sendLinkMessage(String title, String text, String messageUrl) {return this.sendMessage(new LinkMessage(title, text, messageUrl));}/*** 发送Link消息到钉钉** @param title* @param text* @param messageUrl* @param picUrl* @return*/public DingTalkResponse sendLinkMessage(String title, String text, String messageUrl, String picUrl) {return this.sendMessage(new LinkMessage(title, text, messageUrl, picUrl));}/*** 发送MarkDown消息到钉钉** @param message* @return*/public DingTalkResponse sendMarkdownMessage(MarkdownMessage message) {return this.sendMessage(message);}/*** 发送MarkDown消息到钉钉** @param title* @param text* @return*/public DingTalkResponse sendMarkdownMessage(String title, String text) {return this.sendMessage(new MarkdownMessage(title, text));}/*** 发送MarkDown消息到钉钉** @param title* @param text* @param atMobiles* @return*/public DingTalkResponse sendMarkdownMessage(String title, String text, String[] atMobiles) {return this.sendMessage(new MarkdownMessage(title, text, atMobiles));}/*** 发送MarkDown消息到钉钉** @param title* @param text* @param isAtAll* @return*/public DingTalkResponse sendMarkdownMessage(String title, String text, boolean isAtAll) {return this.sendMessage(new MarkdownMessage(title, text, isAtAll));}public static void main(String[] args) {new DingTalkRobotClient("accessToken").sendMarkdownMessage("构建任务","#### 杭州天气 @156xxxx8827\n" +"> 9度,西北风1级,空气良89,相对温度73%\n\n" +"> \n" +"> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) \n");}
6. DingTalkConfig配置
@ConfigurationProperties(prefix = "dingtalk")
@Configuration
@Data
public class DingTalkConfig {private String accessToken;@Beanpublic DingTalkRobotClient dingTalkRobotClient(){return new DingTalkRobotClient(accessToken);}
}
相关文章:
java实现钉钉机器人消息推送
项目开发中需要用到钉钉机器人发送任务状态,本来想单独做一个功能就好,但是想着公司用到钉钉机器人发送项目挺多的。所以把这个钉钉机器人抽离成一个组件发布到企业maven仓库,这样可以给其他同事用提高工作效率。 1.目录结构 2.用抽象类&…...
C语言之break continue详解
C语言之break continue 文章目录 C语言之break continue1. break 和 continue2. while语句中的break和continue2.1break和continue举例 3. for语句中的break和continue3.1break和continue举例 1. break 和 continue 循环中break和continue 在循环语句中,如果我达到…...
mysql group by 执行原理及千万级别count 查询优化
大家好,我是蓝胖子,前段时间mysql经常碰到慢查询报警,我们线上的慢sql阈值是1s,出现报警的表数据有 7000多万,经常出现报警的是一个group by的count查询,于是便开始着手优化这块,遂有此篇,记录下…...
Linux的几个常用基本指令
目录 1. ls 指令2.pwd命令3.cd 指令4. touch指令5.mkdir指令6.rmdir指令 && rm 指令7.man指令8.cp指令9.mv指令10.cat指令 1. ls 指令 语法: ls [选项][目录或文件] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件&…...
mac中安装Homebrew
1、Homebrew是什么? 软件安装管理工具 2、先检查电脑中是否已经安装了Homebrew 打开终端输入:brew 提示命令没有找到,说明电脑没有安装Homebrew 如果提示上述图片说明Homebrew已经安装成功 3、安装Homebrew 进入https://brew.sh/ 复制的命…...
Vue23的计算属性(computed)
Vue2&3的计算属性(computed) Vue2的计算属性 原理:data中的属性通过计算得到新的属性,称为计算属性(computed)。computed 具有 getter 和 setter 属性 getter 属性在使用时分别有两次调用:…...
vue3中祖孙组件之间的通信provide和inject
一、在vue3中新增的祖孙之间通信的方式 provide和inject是Vue中的两个相关功能,它们一起提供了一种祖孙组件之间共享数据的方式。父组件可以使用provide来提供数据,而子孙组件可以使用inject来接收这些数据。 二、使用 父组件中部分代码 <script&g…...
月影下的时光机:Python中的日期、时间、农历、节气和时区探秘
前言 在现代软件开发中,对日期、时间和时区的准确处理至关重要。无论是全球化应用的开发,还是与时序数据相关的任务,都需要强大而灵活的工具。Python作为一门流行的编程语言,提供了丰富的标准库和第三方库,使得处理日…...
【Bazel】Bazel 学习笔记
本文简单记录下 Bazel 使用过程中的一些知识点。 目录 文章目录 目录Bazel 目录结构BUILD 构建规则常用构建规则 Bazel 命令bazel buildbazel query Mac 安装 Bazel Bazel 是谷歌推出的一个开源的构建工具,工作原理与 make、maven 或 gradle 等其他构建工具类似。但…...
2023年“华为杯”第二十届中国研究生数学建模成绩数据分析(末尾有吃席群)
目录 0引言1、数据大盘1.1 官方数据1.2 分赛题统计数据1.2.1 A-F 获奖数1.2.2 A-F 获奖率 2、分学校统计获奖情况(数模之星没有统计)3、 数模之星4、吃席群5、写在最后的话 0引言 2023年华为杯成绩于2023年9月22-26日顺利举行,来自国际和全国…...
Linux文件和文件夹命令详解
1.Linux文件类型详解 常见的Linux文件类型: 普通文件(Regular File):(例如文本文件、二进制文件、图片、视频和压缩文件等;) 普通文件是最常见的文件类型,存储了实际的数据…...
MIKE水动力笔记20_由dfs2网格文件提取dfs1断面序列文件
本文目录 前言Step 1 MIKE Zero工具箱Step 2 提取dfs1 前言 在MIKE中,dfs2是一个一个小格格的网格面的时间序列文件,dfs1是一条由多个点组成的线的时间序列文件。 如下两图: 本博文内容主要讲如何从dfs2网格文件中提取dfs1断面序列文件。 …...
微服务nacos实战入门
注册中心 在微服务架构中,注册中心是最核心的基础服务之一 主要涉及到三大角色: 服务提供者 ---生产者 服务消费者 服务发现与注册 它们之间的关系大致如下: 1.各个微服务在启动时,将自己的网络地址等信息注册到注册中心&#x…...
PyCharm 远程连接服务器并使用服务器的 Jupyter 环境
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
HBase中的数据表是如何用CHAT进行分区的?
问CHA:HBase中的数据表是如何进行分区的? CHAT回复: 在HBase中,数据表是水平分区的。每一个分区被称为一个region。当一个region达到给定的大小限制时,它会被分裂成两个新的region。 因此,随着数据量的增…...
rabbitMQ的direct模式的生产者与消费者使用案例
消费者C1的RoutingKey 规则按照info warn 两种RoutingKey匹配 绑定队列console package com.esint.rabbitmq.work03;import com.esint.rabbitmq.RabbitMQUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.DeliverCallback;/*** 消费者01的消息接受*/ p…...
分布式应用服务拆分
需求落地分布式应用服务 将需求转化为分布式应用服务的过程可以按照以下步骤进行: 理解需求:首先,你需要仔细阅读和理解业务需求。与相关的利益相关者(如业务分析师、产品经理等)进行沟通,确保你对需求的理…...
matplotlib 绘制双纵坐标轴图像
效果图: 代码: 由于使用了两组y axis,如果直接使用ax.legend绘制图例,会得到两个图例。而下面的代码将两个图例合并显示。 import matplotlib.pyplot as plt import numpy as npdata np.random.randint(low0,high5,size(3,4)) …...
74基于matlab的PSO-ELM的多输入,单输出结果预测,输出训练集和测试机预测结果及误差。
基于matlab的PSO-ELM的多输入,单输出结果预测,输出训练集和测试机预测结果及误差,适应度值。数据可更换自己的,程序已调通,可直接运行。 74matlabPSO-ELM多输入单输出 (xiaohongshu.com)...
shell之head命令
head命令 head命令是UNIX和Linux环境中常用的命令,用于在标准输出上显示文件的开头内容。 具体来说,head命令默认会显示给定文件开头的10行内容。如果指定了多个文件名,head命令会逐个显示每个文件的开头内容,并在每个文件显示的…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
