spring boot 整合钉钉机器人发送消息通知

钉钉消息通知

主要用于系统预警、资源预警、重要消息通知,随时随地可以掌握重要信息

一、通知效果

1.文本通知

spring boot 整合钉钉机器人发送消息通知_第1张图片

spring boot 整合钉钉机器人发送消息通知_第2张图片

2.带链接的通知

spring boot 整合钉钉机器人发送消息通知_第3张图片

spring boot 整合钉钉机器人发送消息通知_第4张图片

3.makrdown格式 通知

spring boot 整合钉钉机器人发送消息通知_第5张图片

spring boot 整合钉钉机器人发送消息通知_第6张图片

4.ActionCard 通知

spring boot 整合钉钉机器人发送消息通知_第7张图片

spring boot 整合钉钉机器人发送消息通知_第8张图片

5.Feedcard 消息通知

spring boot 整合钉钉机器人发送消息通知_第9张图片

spring boot 整合钉钉机器人发送消息通知_第10张图片

二、使用方法

1.新建一个消息通知群,用于消息通知

spring boot 整合钉钉机器人发送消息通知_第11张图片
spring boot 整合钉钉机器人发送消息通知_第12张图片

spring boot 整合钉钉机器人发送消息通知_第13张图片
spring boot 整合钉钉机器人发送消息通知_第14张图片
spring boot 整合钉钉机器人发送消息通知_第15张图片
复制这个加签的字符串,后面会用到

spring boot 整合钉钉机器人发送消息通知_第16张图片
记住这个webhook,反而也会用到

2. 新建 spring boot 工程

spring boot 整合钉钉机器人发送消息通知_第17张图片

2.1 POM 文件

<dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-configuration-processorartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.78version>
        dependency>
    dependencies>

2.2 配置文件 application.yml

#集成钉钉服务
ding:
  robot:
    # webhook
    webhook: ### webhook ###
    # 加签
    key: ### 加签 ###

2.3 消息模型 SendRequestParam

package com.billow.ding;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

@Data
public class SendRequestParam implements Serializable
{
    private SendRequestParam.Actioncard actionCard;
    private SendRequestParam.At at;
    private SendRequestParam.Feedcard feedCard;
    private SendRequestParam.Link link;
    private SendRequestParam.Markdown markdown;
    private SendRequestParam.Text text;
    private String msgtype;

    @Data
    public static class Text implements Serializable
    {
        private static final long serialVersionUID = 2112411828946494293L;

        private String content;
    }

    @Data
    public static class Link implements Serializable
    {
        private static final long serialVersionUID = 7833398226941254374L;
        private String messageUrl;
        private String picUrl;
        private String text;
        private String title;
    }

    @Data
    public static class Markdown implements Serializable
    {
        private static final long serialVersionUID = 4697553615692276546L;
        private String text;
        private String title;
    }

    @Data
    public static class At implements Serializable
    {
        private static final long serialVersionUID = 6328897894299426499L;
        private List<String> atMobiles;
        private List<String> atUserIds;
        private Boolean isAtAll;
    }


    @Data
    public static class Actioncard implements Serializable
    {
        private static final long serialVersionUID = 1553944892187227581L;
        private String btnOrientation;
        private List<SendRequestParam.Btns> btns;
        private String hideAvatar;
        private String singleTitle;
        private String singleURL;
        private String text;
        private String title;
    }

    @Data
    public static class Feedcard implements Serializable
    {
        private static final long serialVersionUID = 6578287939968676945L;
        private List<SendRequestParam.Links> links;
    }

    @Data
    public static class Btns implements Serializable
    {
        private static final long serialVersionUID = 4435422339746837645L;
        private String actionURL;
        private String title;
    }

    @Data
    public static class Links implements Serializable
    {
        private static final long serialVersionUID = 7496318843524412877L;
        private String messageURL;
        private String picURL;
        private String title;
    }
}

2.4 发送消息服务 SendDingService

package com.billow.ding;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Slf4j
@Service
public class SendDingService
{
    @Value("${ding.robot.webhook}")
    private String robotWebhook;

    @Value("${ding.robot.key}")
    private String robotKey;

    @Autowired
    private RestTemplate restTemplate;

    private final static String MSG_TYPE_TEXT = "text";
    private final static String MSG_TYPE_LINK = "link";
    private final static String MSG_TYPE_MARKDOWN = "markdown";
    private final static String MSG_ACTION_CARD = "actionCard";
    private final static String MSG_FEED_CARD = "feedCard";

    private ThreadLocal<SendRequestParam> paramLocal = new ThreadLocal<>();

    /**
     * 发送文本消息
     *
     * @param text
     * @return OapiRobotSendRequest
     * @author 千面
     * @date 2021/11/25 21:21
     */
    public SendDingService sendText(SendRequestParam.Text text)
    {
        SendRequestParam request = new SendRequestParam();
        request.setText(text);
        request.setMsgtype(MSG_TYPE_TEXT);
        paramLocal.set(request);
        return this;
    }

    /**
     * 发送带连接的消息
     *
     * @param link
     * @return OapiRobotSendRequest
     * @author 千面
     * @date 2021/11/25 21:21
     */
    public SendDingService sendLink(SendRequestParam.Link link)
    {
        SendRequestParam request = new SendRequestParam();
        request.setMsgtype(MSG_TYPE_LINK);
        request.setLink(link);
        paramLocal.set(request);
        return this;
    }

    /**
     * 发送markdown消息
     *
     * @param markdown
     * @return OapiRobotSendRequest
     * @author 千面
     * @date 2021/11/25 21:21
     */
    public SendDingService sendMarkdown(SendRequestParam.Markdown markdown)
    {
        SendRequestParam request = new SendRequestParam();
        request.setMsgtype(MSG_TYPE_MARKDOWN);
        request.setMarkdown(markdown);
        paramLocal.set(request);
        return this;
    }

    public String sendActionCard(SendRequestParam.Actioncard actioncard)
    {
        SendRequestParam request = new SendRequestParam();
        request.setMsgtype(MSG_ACTION_CARD);
        request.setActionCard(actioncard);
        paramLocal.set(request);
        return this.send();
    }


    public String sendFeedcard(SendRequestParam.Feedcard feedcard)
    {
        SendRequestParam request = new SendRequestParam();
        request.setMsgtype(MSG_FEED_CARD);
        request.setFeedCard(feedcard);
        paramLocal.set(request);
        return this.send();
    }

    /**
     * 推送钉钉机器人消息
     *
     * @return
     */
    public String send()
    {
        return this.send(null);
    }

    /**
     * 推送钉钉机器人消息
     *
     * @return
     */
    public String send(SendRequestParam.At at)
    {
        String json = null;
        String dingUrl = null;
        try
        {
            dingUrl = this.getDingUrl();
            //组装请求内容
            SendRequestParam param = paramLocal.get();
            param.setAt(at);
            json = JSON.toJSONString(param);
            return sendRequest(dingUrl, json);
        }
        catch (Exception e)
        {
            log.error("盯盯消息发送错误,接口地址:[{}],请求参数:[{}]", dingUrl, json, e);
        }
        finally
        {
            paramLocal.remove();
        }
        return null;
    }

    /**
     * 获取 钉钉机器人地址
     *
     * @param
     * @return String
     * @author 千面
     * @date 2021/11/26 13:36
     */
    private String getDingUrl()
    {
        long timestamp = System.currentTimeMillis();
        String sign = HmacSha256Util.dingHmacSHA256(System.currentTimeMillis(), robotKey);
        // 钉钉机器人地址(配置机器人的 webhook) https://oapi.dingtalk.com/robot/send?access_token=XXXXXX×tamp=XXX&sign=XXX
        return String.format(robotWebhook + "×tamp=%d&sign=%s", timestamp, sign);
    }

    private String sendRequest(String url, String params)
    {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> httpEntity = new HttpEntity<>(params, headers);
        ResponseEntity<String> entity = restTemplate.postForEntity(url, httpEntity, String.class);
        String body = entity.getBody();
        log.info("sendRequest()>>>[{}]", body);
        return body;
    }
}

2.5 加签算法 HmacSha256Util

package com.billow.ding;

import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;

@Slf4j
public class HmacSha256Util
{
    /**
     * 钉钉自定义机器人安全设置
     * 把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)
     *
     * @param secret
     * @return
     */
    /**
     * 钉钉自定义机器人安全设置
     *
     * @param timestamp
     * @param secret
     * @return String
     * @author 千面
     * @date 2021/11/26 14:05
     */
    public static String dingHmacSHA256(long timestamp, String secret)
    {
        try
        {
            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;
        }
        catch (Exception e)
        {
            log.error("dingHmacSHA256加密失败", e);
        }
        return null;
    }
}

2.6 测试 TestApi

package com.billow;

import com.billow.ding.SendDingService;
import com.billow.ding.SendRequestParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class TestApi
{

    @Autowired
    private SendDingService sendDingService;

    @GetMapping("/sendText")
    public String sendText()
    {
        SendRequestParam.Text text = new SendRequestParam.Text();
        text.setContent("我就是我, @XXX 是不一样的烟火");

//        // at 指定人
//        at.setAtMobiles(Arrays.asList("185XXXXXXXX"));
//        // at 所有人
//        at.setIsAtAll(true);
//        return sendDingService.sendText(text).send(at);

        return sendDingService.sendText(text).send();
    }

    @GetMapping("/sendLink")
    public String sendLink()
    {
        SendRequestParam.Link link = new SendRequestParam.Link();
        link.setText("这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林");
        link.setTitle("时代的火车向前开");
        link.setPicUrl("https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png");
        link.setMessageUrl("https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI");
        return sendDingService.sendLink(link).send();
    }

    @GetMapping("/sendMarkdown")
    public String sendMarkdown()
    {
        SendRequestParam.Markdown markdown = new SendRequestParam.Markdown();
        markdown.setTitle("这个即将发布的新版本,创始人xx称它为红树林。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是红树林");
        markdown.setText("#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > ![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png)\n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n");
        return sendDingService.sendMarkdown(markdown).send();
    }

    @GetMapping("/sendActionCard")
    public String sendActionCard()
    {
        SendRequestParam.Actioncard actioncard = new SendRequestParam.Actioncard();
        actioncard.setTitle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身");
        actioncard.setText("![screenshot](https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png) \n" +
                " ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
                " Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
//        actioncard.setSingleTitle("阅读全文");
//        actioncard.setSingleURL("https://www.dingtalk.com/");
        // 0:按钮竖直排列 1:按钮横向排列
        actioncard.setBtnOrientation("1");
        // 添加按钮
        List<SendRequestParam.Btns> btns = new ArrayList<>();
        SendRequestParam.Btns btn1 = new SendRequestParam.Btns();
        btn1.setTitle("查看");
        btn1.setActionURL("");
        btns.add(btn1);
        SendRequestParam.Btns btn2 = new SendRequestParam.Btns();
        btn2.setTitle("取消");
        btns.add(btn2);
        btn1.setActionURL("");

        actioncard.setBtns(btns);
        return sendDingService.sendActionCard(actioncard);
    }

    @GetMapping("/sendFeedcard")
    public String sendFeedcard()
    {
        SendRequestParam.Feedcard feedcard = new SendRequestParam.Feedcard();

        List<SendRequestParam.Links> links = new ArrayList<>();
        SendRequestParam.Links links1 = new SendRequestParam.Links();
        links1.setTitle("时代的火车向前开1");
        links1.setMessageURL("https://www.dingtalk.com/");
        links1.setPicURL("https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png");
        links.add(links1);

        SendRequestParam.Links links2 = new SendRequestParam.Links();
        links2.setTitle("时代的火车向前开2");
        links2.setMessageURL("https://www.dingtalk.com/");
        links2.setPicURL("https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png");
        links.add(links2);

        feedcard.setLinks(links);

        return sendDingService.sendFeedcard(feedcard);
    }
}

盯盯官方文档

你可能感兴趣的:(javaSE,服务器,javaEE,java,消息通知,系统预警,盯盯,盯盯消息通知)