java实现钉钉机器人消息推送

news2024/11/27 17:48:13

项目开发中需要用到钉钉机器人发送任务状态,本来想单独做一个功能就好,但是想着公司用到钉钉机器人发送项目挺多的。所以把这个钉钉机器人抽离成一个组件发布到企业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;
    }

    @Override
    protected void initMsg() {
        this.msgType = DingTalkMsgEnum.LINK.getType();
    }

    @Override
    public 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;
    }


    @Override
    protected void initMsg() {
        this.msgType = DingTalkMsgEnum.TEXT.getType();
    }

    @Override
    public 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;
    }

    @Override
    protected void initMsg() {
        this.msgType = DingTalkMsgEnum.MARKDOWN.getType();
    }

    @Override
    public 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;
    }

    @Override
    public 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" +
                "> ![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png)\n"  +
                "> ###### 10点20分发布 [天气](http://www.thinkpage.cn/) \n");
    }

6. DingTalkConfig配置

@ConfigurationProperties(prefix = "dingtalk")
@Configuration
@Data
public class DingTalkConfig {

    private String accessToken;

    @Bean
    public DingTalkRobotClient dingTalkRobotClient(){
        return new DingTalkRobotClient(accessToken);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1216505.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享6个超绝的设计素材网站,绝对好用!

设计师平时都去哪里找素材呢?收藏好这6个网站,绝对能解决你80%的素材需求,话不多说,直接上干货。 设计素材 1、菜鸟图库 https://www.sucai999.com/?vNTYxMjky 菜鸟图库是一个非常大的素材库,站内包含设计、办公、自…

前端常用的几种加密方法

文章目录 前端常用的几种加密方法md5 加密(不可逆)base64 位加密(可加密可解密)RSA 加密(公钥加密,私钥解密)AES 加密(需要密钥才能解密)CryptoJS 常用的加密方式--demo ✒️总结 前端常用的几种加密方法 在信息安全越来越受重视的今天,JS 安全一直是前端…

【文件上传】upload-labs 通关

环境准备 靶场upload-labs-env-win-0.1环境windows 靶场描述 靶场攻略 Pass-01 1.上传一句话木马 发现有类型限制 2.上传图片木马 抓包 3.修改后缀 将png修改为php. 成功上传, 4.查找文件地址 5.中国蚁剑连接 6.成功 7.源码分析 function checkFile() {var fi…

计算机组成原理——第一章

早期冯诺依曼机: 现代计算机: 五大部分: 1. 输入设备,是指将外部信息以计算机能读懂的方式输入进来,如键盘,鼠标等 2.输出设备,就是将计算机处理的信息以人所能接受的方式输出出来,比…

【问题解决】蓝牙显示已配对,无法连接,蓝牙设备显示在其他设备中。

最开始,我发现逻辑鼠标无法连接蓝牙了,怎么都不行,重连,重新配对,全不行。于是尝试用逻辑鼠标内的usb接口进行解决,重连成功。 然而,在连接耳机的时候,发现耳机音频同样无法连接&am…

2023数维杯国际赛数学建模竞赛选题建议及D题思路讲解

大家好呀,2023年第九届数维杯国际大学生数学建模挑战赛今天早上开赛啦,在这里先带来初步的选题建议及思路。 目前团队正在写B题和D题完整论文,后续还会持续更新哈,大家三连关注一下防止迷路。 注意,本文只是比较简略…

golang 解析oracle 数据文件头

package mainimport ("encoding/binary""fmt""io""os" ) // Powered by 黄林杰 15658655447 // Usered for parser oracle datafile header block 1 .... // oracle 数据文件头块解析 // KCBlockStruct represents the structure of t…

全链路压测:确保系统稳定性的关键一环

在当今高度数字化的业务环境中,系统的稳定性和性能至关重要。全链路压测作为确保系统在各种负载下依然可靠运行的关键工具,越来越受到企业的关注。本文将深入探讨全链路压测的概念及目的。 一、全链路压测概念 全链路压测是一种模拟真实用户行为、模拟全…

人人商城app禁用

api.map.baidu.com 换成 lbs.map.baidu.com

计算机网络:网络层ARP协议

在实现IP通信时使用了两个地址:IP地址(网络层地址)和MAC地址(数据链路层地址) 问题:已知一个机器(主机或路由器)的IP地址,如何找到相应的MAC地址? 为了解决…

μC/OS-II---整理学习1

目录 系统功能系统结构图 μC/OS-II是用 C 语言(绝大部分)和汇编语言(与处理器密切相关的代码)编写的。 系统功能 实时内核:μC/OS-II—内核:任务调度(oc_core.c)任务管理&#xf…

Python爬虫实战(进阶篇)—7获取每日菜价(附完整代码)

文章目录 专栏导读背景前期准备1、网址:2、分析: 请求url、请求方法、请求参数测试一个完整代码写入Excel视频展示不足:结尾 专栏导读 🔥🔥本文已收录于《Python基础篇爬虫》 🉑🉑本专栏专门针…

IaaS、PaaS、SaaS 的区别

文章1:软件系统的分类 文章2:有哪些通俗易懂的例子可以解释 IaaS、PaaS、SaaS 的区别?——原文 写的很好的两篇文章值得一看 你一定听说过云计算中的三个“高大上”的你一定听说过云计算中的三个“高大上”的概念:IaaS、PaaS和…

【Java 进阶篇】JQuery 案例:qq表情选择,表达情感的小黄脸

在我们的数字交流时代,表情符号已成为表达情感的重要方式之一。为了丰富用户的输入体验,qq表情选择功能应运而生。通过巧妙运用 JQuery,我们可以在页面中实现一个生动活泼的表情选择框,让用户轻松表达各种情感。本篇博客将深入探讨…

使用量子玻尔兹曼机推进机器学习:新范式

一、说明 量子玻尔兹曼机(QBM)是量子物理学和机器学习的前沿融合。通过利用叠加和纠缠等量子特性的力量,QBM 可以同时探索多个解决方案,使其异常擅长解决复杂问题。它使用量子位(量子计算的构建模块)以传统…

所有社区工作者!能救一个是一个

救命啊,这东西我怎么早不知道呢! 社区人到年底了各种要写的东西很烦啊!突然看到这个,真的救我大命了啊! 谁懂啊?!!平时写个东西起码两三天,试了一下这东西!…

阅读记录 The Aggregation–Heterogeneity Trade-off in Federated Learning

The Aggregation–Heterogeneity Trade-off in Federated Learning Abstract 机器学习的传统观点认为,训练模型的数据越多,模型的性能就越好。因此,人们开发了多种联邦学习方法来聚合尽可能多的本地样本。与这种观点相反,本文表…

营收连续上涨,一脉阳光能否打造“医学影像独角兽”?

自2018年完成B轮融资的一脉阳光,时隔四年,于今年11月13日向港交所发起冲刺。作为国内唯一一家为整个医学影像产业链提供多元化服务的医学影像平台运营商及管理者,一脉阳光受到多家投资机构的青睐,高盛、新浚资本多次追加投资。 此…

网络和Linux网络_2(套接字编程)socket+UDP网络通信代码

目录 1. 预备知识 1.1 源IP地址和目的IP地址 1.2 端口号port和套接字socket 1.3 网络通信的本质 1.4 TCP和UDP协议 1.5 网络字节序 2. socket套接字 2.1 socket创建套接字 2.2 bind绑定 2.3 sockaddr结构体 3. UDP网络编程 3.1 server的初始化服务器 3.2 server的…

使用阿里云Logstash,从自建es6.2.4迁移数据至云ES7.10测试

一、购买阿里云Logstash服务 4C16G 40G 高效云盘 二、配置管道 2.1 配置启动管道前置工作 logstash要通源端ES网络及http端口,且加白logstash要通目标端ES网络及http端口,且加白目标端ES加配置自动创建索引配置管道前先安装 logstash-output-file_extend插件目标云ES7.10要…