简单几步,项目接入钉钉机器人通知

343 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情


如果是前期开发测试,可以先建一个签到打卡群一个人进行测试;

钉钉上,发起群聊,选择建场景群

image.png

选择签到打卡群

image.png

这种类型的群一个人也是能建立的。

在群设置 - 智能群助手 - 添加机器人

image.png

选择自定义

image.png

安全设置选择加签

image.png

创建后,把这个webhook和刚刚加签的密钥都复制保存下

image.png

项目中添加个 jar 包

<dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>alibaba-dingtalk-service-sdk</artifactId>
    <version>1.0.1</version>
</dependency>

配置文件加两个配置

spring:
    dingtalk:
        access-token: d0f2317666ef951d52ccd7d181f97e3f1234f756dbcd1f83f01e31117ae31f4s
        secret: SEC43789e33b617c5741f54ed77ca114f1f1d6570b3468341ae0df631e8e4312d0

access-token 就是 webhook 链接后面的那一串;

secret 是选择加签生成的那串密钥;

发送信息的代码,这里演示的是 发送 Markdown 类型 的内容;

import cn.hutool.json.JSONUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

@Slf4j
@Component
public class DingTalkUtil {

    private static String accessToken;
    private static String secret;

    @Value("${spring.dingtalk.access-token}")
    public void getToken(String accessToken) {
        DingTalkUtil.accessToken = accessToken;
    }

    @Value("${spring.dingtalk.secret}")
    public void getSecret(String secret) {
        DingTalkUtil.secret = secret;
    }

    public void sendMsg(Object msg) {
        if (StringUtils.isBlank(accessToken) || StringUtils.isBlank(secret)) {
            log.info("【DingTalkUtil -> sendMsg】未配置钉钉accessToken和secret");
            return;
        }
        DingTalkClient client = new DefaultDingTalkClient(getServerUrl());
        OapiRobotSendRequest request = new OapiRobotSendRequest();
        request.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown md = new OapiRobotSendRequest.Markdown();
        md.setTitle("服务异常通知");
        md.setText("### 服务异常:\n" + ">" + msg);
        request.setMarkdown(md);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setIsAtAll(true);
        OapiRobotSendResponse response = null;
        try {
            response = client.execute(request);
        } catch (ApiException e) {
            e.printStackTrace();
        }
        log.info("【DingTalkUtil -> sendMsg】response:{}", JSONUtil.toJsonStr(response));
    }

    private String getServerUrl() {
        String defaultUrl = "https://oapi.dingtalk.com/robot/send";
        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");
            return defaultUrl + "?access_token=" + accessToken + "&timestamp=" + timestamp + "&sign=" + sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defaultUrl;
    }

}

在工具类里怎样使用@Value()注解获取到配置文件里的值?

如上代码所示,在类上使用 @Component 注解 和在方法上加 @Value() 的方式,可以获取到配置文件里设置的内容

private static String accessToken; 

private static String secret; 

@Value("${spring.dingtalk.access-token}") 
public void getToken(String accessToken) { 
    DingTalkUtil.accessToken = accessToken; 
} 

@Value("${spring.dingtalk.secret}") 
public void getSecret(String secret) { 
    DingTalkUtil.secret = secret; 
}

发送的消息类型,除了 markdown类型 外 ,还可以发送 text类型link类型整体跳转ActionCard类型独立跳转ActionCard类型FeedCard类型

具体示例可以看下面的官方文档,自己调整发送信息的格式

自定义机器人安全设置

这里有发送不同消息类型的示例

使用的话,就简单了,如果有配置全局异常处理的地方,直接在那里调用该方法就行了

把这个类注入进来,直接调用 sendMsg 方法即可。


@Resource
private DingTalkUtil dingTalkUtil;

@ExceptionHandler(value = {RuntimeException.class, Exception.class})
public BaseResult exception(Exception e) {
    dingTalkUtil.sendMsg(ExceptionUtils.getStackTrace(e));
    return xxx;
}

ExceptionUtils 是 org.apache.commons.lang.exception 下带的工具类;

功能是把 Throwable 转换成 String 类型

public static String getStackTrace(Throwable throwable) {
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw, true);
    throwable.printStackTrace(pw);
    return sw.getBuffer().toString();
}

反正就是哪里需要发消息通知,就直接调用该方法就行。

开发测试完后,就可以新建个通知群,重新添加机器人,把配置文件中的 token 和 secret 替换掉就可以了;