SpringBoot + Java 实现钉钉机器人消息推送(完整工具类 + 文本/Markdown/图片/链接
在日常研发中,尤其是做 任务调度、异常监控、系统告警 时,我们经常需要快速通知到相关人员。
钉钉机器人就是一个非常轻量、好用、免费的方案。
今天分享一个 完整可用的钉钉机器人工具类,包含:
-
文本消息(Text)
-
Markdown 消息
-
链接消息(Link)
-
图片消息(Image)
-
自动签名(HmacSHA256)
-
完整日志可追踪
支持直接在 Java 工程中使用(SpringBoot)。
一、钉钉机器人原理说明
钉钉自定义机器人有两种安全模式:
-
Signature(加签模式)
-
IP 限制模式
本文使用操作最安全通用的 加签方式。
每次发送消息都需要三要素:
-
webhook 地址(accessToken)
-
secret(加签密钥)
-
时间戳 + secret 用 HmacSHA256 生成 sign
二、工具类完整代码
下面是可直接复制使用的工具类,支持四种消息类型。
1.添加依赖项到工程的pom.xml文件
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
</dependencies>
2.yml 配置中加入:
ding:
secret: 你的secret
url: https://oapi.dingtalk.com/robot/send?access_token=xxxx
3.DingTalkUtil.java
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
/**
* 钉钉机器人工具类
* 支持以下消息类型:
* 1. 文本消息(Text)
* 2. Markdown 消息
* 3. 链接消息(Link)
* 4. 图片消息(Image)
* @author xiaomai
*/
public class DingTalkUtil {
private static final Logger log = LoggerFactory.getLogger(DingTalkUtil.class);
/**
* 钉钉机器人配置常量
*/
@Value("${ding.secret}")
private static final String SECRET = "SECxxxxxxxx";
@Value("${ding.url}")
private static final String DINGTALK_BASE_URL = "https://oapi.dingtalk.com/robot/send?access_token=d77xxxxxxx";
//==================== 公共发送方法 ====================//
/**
* 发送文本消息
*
* @param content 消息内容
* @param isAtAll 是否通知所有人
* @param mobiles 指定通知的手机号列表,可为空
*/
public static void sendText(String content, boolean isAtAll, List<String> mobiles) {
sendMessage(buildTextMsg(content, isAtAll, mobiles));
}
/**
* 发送 Markdown 消息
*
* @param title 消息标题
* @param markdownContent Markdown 内容
* @param isAtAll 是否通知所有人
* @param mobiles 指定通知的手机号列表,可为空
*/
public static void sendMarkdown(String title, String markdownContent, boolean isAtAll, List<String> mobiles) {
sendMessage(buildMarkdownMsg(title, markdownContent, isAtAll, mobiles));
}
/**
* 发送链接消息
*
* @param title 消息标题
* @param text 消息内容
* @param messageUrl 点击跳转链接
* @param picUrl 图片链接,可为空
*/
public static void sendLink(String title, String text, String messageUrl, String picUrl) {
sendMessage(buildLinkMsg(title, text, messageUrl, picUrl));
}
/**
* 发送图片消息
*
* @param base64 图片 Base64 内容
* @param md5 图片 MD5 校验值
*/
public static void sendImage(String base64, String md5) {
sendMessage(buildImageMsg(base64, md5));
}
//==================== 核心发送方法 ====================//
/**
* 核心方法:发送钉钉消息
*
* @param reqJson 已组装好的请求 JSON 字符串
*/
private static void sendMessage(String reqJson) {
try {
// 获取时间戳
long timestamp = System.currentTimeMillis();
// 按钉钉加签规则生成签名
String stringToSign = timestamp + "\n" + SECRET;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(SECRET.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
String sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
// 构建完整请求 URL
String url = DINGTALK_BASE_URL + "×tamp=" + timestamp + "&sign=" + sign;
// 发送 POST 请求
String result = HttpUtil.post(url, reqJson);
log.info("DingTalk push result: {}", result);
} catch (Exception e) {
log.error("DingTalk message send failed", e);
}
}
//==================== 构建消息体 ====================//
/**
* 构建文本消息 JSON
*/
private static String buildTextMsg(String content, boolean isAtAll, List<String> mobiles) {
Map<String, String> textMap = Maps.newHashMap();
textMap.put("content", content);
Map<String, Object> atMap = Maps.newHashMap();
atMap.put("isAtAll", isAtAll);
atMap.put("atMobiles", mobiles != null ? mobiles : Lists.newArrayList());
Map<String, Object> reqMap = Maps.newHashMap();
reqMap.put("msgtype", "text");
reqMap.put("text", textMap);
reqMap.put("at", atMap);
return JSON.toJSONString(reqMap);
}
/**
* 构建 Markdown 消息 JSON
*/
private static String buildMarkdownMsg(String title, String markdownContent, boolean isAtAll, List<String> mobiles) {
Map<String, String> markdownMap = Maps.newHashMap();
markdownMap.put("title", title);
markdownMap.put("text", markdownContent);
Map<String, Object> atMap = Maps.newHashMap();
atMap.put("isAtAll", isAtAll);
atMap.put("atMobiles", mobiles != null ? mobiles : Lists.newArrayList());
Map<String, Object> reqMap = Maps.newHashMap();
reqMap.put("msgtype", "markdown");
reqMap.put("markdown", markdownMap);
reqMap.put("at", atMap);
return JSON.toJSONString(reqMap);
}
/**
* 构建链接消息 JSON
*/
private static String buildLinkMsg(String title, String text, String messageUrl, String picUrl) {
Map<String, String> linkMap = Maps.newHashMap();
linkMap.put("title", title);
linkMap.put("text", text);
linkMap.put("messageUrl", messageUrl);
linkMap.put("picUrl", picUrl != null ? picUrl : "");
Map<String, Object> reqMap = Maps.newHashMap();
reqMap.put("msgtype", "link");
reqMap.put("link", linkMap);
return JSON.toJSONString(reqMap);
}
/**
* 构建图片消息 JSON
*/
private static String buildImageMsg(String base64, String md5) {
Map<String, String> imageMap = Maps.newHashMap();
imageMap.put("base64", base64);
imageMap.put("md5", md5);
Map<String, Object> reqMap = Maps.newHashMap();
reqMap.put("msgtype", "image");
reqMap.put("image", imageMap);
return JSON.toJSONString(reqMap);
}
public static void main(String[] args) {
// 发送文本消息
sendText("测试Text消息 ✅", false, Lists.newArrayList());
// 发送 Markdown 消息
sendMarkdown("Markdown标题", "### 测试Markdown消息\n内容示例 ✅", false, Lists.newArrayList());
// 发送链接消息
sendLink("Link标题", "链接消息内容", "https://www.dingtalk.com", null);
// 图片消息示例(
// sendImage("base64内容", "md5值");
}
}
三、钉钉申请操作步骤
-
-
登录钉钉客户端,选择需要添加机器人的群聊会话。
-
进入群聊会话,单击右上角群设置标识。

-
在群管理栏,单击机器人 > 添加机器人,选择自定义机器人。

- 单击添加,配置机器人信息
-
配置项
说明
机器人头像
单击编辑标识,上传机器人头像。
机器人名字
添加机器人名称
安全设置
安全设置类型:
-
自定义关键词
-
加签
-
IP 地址(段)
安全设置详情参考 自定义机器人安全设置。
(可选)是否开启 Outgoing 机制
通过 @ 群机器人,将消息发送到指定外部服务,还可以将外部服务的响应结果返回到群聊会话。
机器人接收消息类型和数据格式,详情参考 机器人接收消息。
配置完成后,勾选《自定义机器人服务及免责条款》,并单击完成。
支持的消息类型四、支持消息类型
类型
是否支持 @人
说明
Text文本类型
✅
Text 消息 @ 人图例:

Link链接消息
❌
Link 消息图例:

Markdown 类型
✅
Markdown 消息 @ 人图例:

整体跳转 ActionCard 类型
✅
整体跳转 ActionCard 消息 @ 人图例:

独立跳转 ActionCard 类型
✅
独立跳转 ActionCard 消息 @ 人图例:

FeedCard 类型
❌
FeedCard 消息图例:

-
-
更多推荐


所有评论(0)