从头开始,并不意味着失败,相反,正是拥抱成功的第一步,即使还会继续失败
上一章简单介绍了 SpringBoot 发送邮件(四十三), 如果没有看过,请观看上一章
钉钉消息推送, 官方文档: https://open.dingtalk.com/document/group/group-robot
开发钉钉消息推送,我们可以使用 spring-boot-dingtalk-robot-starter 第三方依赖进行快速开发.
对应的官方文档是: https://gitee.com/snowheart/dingtalk-robot
一. 钉钉群安装机器人
点击进入一个群, 选择智能群助手
选择 添加机器人:
点击 右边的设置
选择 自定义
点击添加:
完成之后,会生成一个相应 的 Webhook
https://oapi.dingtalk.com/robot/send?access_token=817edae9c6xxxxxxxxxxxxxxx
二. 钉钉消息推送开发
二.一 pom.xml 添加依赖
<dependency>
<groupId>cn.snowheart</groupId>
<artifactId>spring-boot-dingtalk-robot-starter</artifactId>
<version>1.0.2.RELEASE</version>
</dependency>
二.二 添加配置
application.yml 上添加配置, 只添加一个对应的 webhook 值即可。 webhook 是 群创建机器人的标识
dingtalk:
robot:
webhook: https://oapi.dingtalk.com/robot/send?access_token=817edae9c662dc38bb5fcb4231f74b9e1eb9f33d17f1e12b25903980f82b7c9d
二.三 功能测试
先注入客户端
@Autowired
@Qualifier("dingTalkRobotClient")
private DingTalkRobotClient client;
二.三.一 普通文本通知
@Test
public void testSendTextMessage() throws InterruptedException {
DingTalkResponse response = null;
response = client.sendTextMessage(new TextMessage("业务报警:构建 TextMessage对象发布!"));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendTextMessage("业务报警:构建普通字符串发布!");
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendTextMessage("业务报警:通知指定人!", new String[]{"15734078927"});
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendTextMessage("业务报警:通知群内所有人!", true);
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
}
二.三.二 超链接文本
@Test
public void testSendLinkMessage() throws InterruptedException {
DingTalkResponse response = null;
//链接,构建 LinkMessage 对象
response = client.sendLinkMessage(new LinkMessage("业务报警:AAA",
"BBBBBBB",
"CCCCC",
"DDDD"));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
}
二.三.三 markdown 文本推送
private static final String markDownDemoText = "业务报警:标题" +
"# 一级标题\n" +
"## 二级标题\n" +
"### 三级标题\n" +
"#### 四级标题\n" +
"##### 五级标题\n" +
"###### 六级标题\n" ;
@Test
public void testSendMarkdownMessage() throws InterruptedException {
DingTalkResponse response = null;
// 构建 markdown 对象用法
response = client.sendMarkdownMessage(new MarkdownMessage("业务报警:钉钉markdown消息支持的语法",
markDownDemoText));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
// 不构建对象
response = client.sendMarkdownMessage("业务报警:钉钉markdown消息支持的语法",
markDownDemoText);
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
// 发送给指定人
response = client.sendMarkdownMessage("业务报警:钉钉markdown消息支持的语法",
markDownDemoText, new String[]{"15734078927"});
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
//发送给全体人
response = client.sendMarkdownMessage("业务报警:钉钉markdown消息支持的语法",
markDownDemoText, true);
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
}
二.三.四 ActionCard 业务推送
@Test
public void testSendActionCardMessage() throws InterruptedException {
DingTalkResponse response = null;
response = client.sendActionCardMessage(new ActionCardMessage("业务报警:This is title", "![screenshot](@lADOpwk3K80C0M0FoA)\n" +
"**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划"));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendActionCardMessage("业务报警:This is title", "![screenshot](@lADOpwk3K80C0M0FoA)\n" +
"**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendActionCardMessage("业务报警:This is title", "![screenshot](@lADOpwk3K80C0M0FoA)\n" +
"**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
HideAvatarType.HIDE);
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendActionCardMessage("业务报警:This is title", "![screenshot](@lADOpwk3K80C0M0FoA)\n" +
"**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
ActionCardButton.defaultReadButton("https://www.dingtalk.com"));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendActionCardMessage("业务报警:This is title", "![screenshot](@lADOpwk3K80C0M0FoA)\n" +
"**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
HideAvatarType.HIDE,
ActionCardButton.defaultReadButton("https://www.dingtalk.com"));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
}
二.三.五 FeedCard 消息推送
@Test
public void testSendFeedCardMessage() throws InterruptedException {
DingTalkResponse response = null;
ArrayList<FeedCardMessageItem> items = new ArrayList<>();
items.add(new FeedCardMessageItem("业务报警:成为架构师的路上,看这一篇文章就足够了,因为……",
"http://mp.weixin.qq.com/s/CPUaB60pue0Zf3fUL9xqvw",
"https://mmbiz.qpic.cn/mmbiz_jpg/YriaiaJPb26VMtfgPvTsM9amH5hf3pmTbf40ia6OLE845icrDb0vt4AsMnTyva5mMMpwwxnkVR5UjCEI8ADvSic1qWQ/640"));
items.add(new FeedCardMessageItem("业务报警:想成为一名Web开发者?你应该学习Node.js而不是PHP",
"http://mp.weixin.qq.com/s/x8dm9e7gwLXSEzxE6sQYow",
"https://mmbiz.qpic.cn/mmbiz_jpg/YriaiaJPb26VND0Q0hSBOoyVkr9cXQrFjWI7hOzax1IxIibqanXYD4W8nyeYX5iaicjgiaqia7ly94iawOsGwehbKGwGsA/640"));
response = client.sendFeedCardMessage(new FeedCardMessage(items));
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
response = client.sendFeedCardMessage(items);
Assert.assertEquals(response.getErrcode().longValue(), 0L);
log.info(response.toString());
Thread.sleep(3000);
}
三. 钉钉业务消息Service 封装
也采用模板的方式进行处理
三.一 接口
public interface DingService {
/**
* 发送普通的文本消息
* @param toArr 发送人, 之间用 ,号分隔
* @param content 发送的内容, 普通文本内容
*/
boolean sendSimpleText(String[] toArr, String content);
/**
* 发送邮件 velocity 模板邮件
* @param title 主题
* @param toArr 发送人
* @param dataMap 发送模板邮件填充数据
* @param templateName 模板名称
*/
boolean sendVelocityText(String title, String[] toArr, Map<String, Object> dataMap, String templateName);
}
三.二 接口实现
@Service
@Slf4j
public class DingServiceImpl implements DingService {
@Autowired
@Qualifier("dingTalkRobotClient")
private DingTalkRobotClient client;
@Value("${dingtalk.robot.webhook}")
private String webhook;
private VelocityEngine velocityEngine;
@PostConstruct
public void initVelocityEngine() {
velocityEngine = new VelocityEngine();
Properties p = new Properties();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
// 配置资源
// velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, "/usr/local/templates/");
velocityEngine.init(p);
}
@Override
public boolean sendSimpleText(String[] toArr, String content) {
//发送信息
try {
TextMessage textMessage = new TextMessage(content,toArr);
DingTalkResponse response = client.sendMessageByURL(webhook, textMessage);
return response.getErrcode() == 0? true :false;
} catch (Exception e) {
log.error("componentAndSendReqeust simple mail error", e);
return false;
}
}
@Override
public boolean sendVelocityText(String title, String[] toArr, Map<String, Object> dataMap, String templateName) {
//发送信息
try {
String velocityMailText = getVelocityMailText(dataMap,templateName);
MarkdownMessage markdownMessage = new MarkdownMessage(title,velocityMailText,toArr);
DingTalkResponse response = client.sendMessageByURL(webhook, markdownMessage);
return response.getErrcode() == 0? true :false;
} catch (Exception e) {
log.error("componentAndSendReqeust simple mail error", e);
return false;
}
}
private String getVelocityMailText(Map<String, Object> dataMap, String templateName) {
VelocityContext velocityContext = new VelocityContext(dataMap);
StringWriter writer = new StringWriter();
velocityEngine.mergeTemplate(templateName, "UTF-8", velocityContext, writer);
return writer.toString();
}
}
三.三 服务测试
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class ServiceTest {
@Resource
private DingService dingService;
@Test
public void simpleEmailTest() {
String[] toArr = new String[]{"15734078927"};
dingService.sendSimpleText(toArr, "钉钉发送消息");
log.info(">>>钉钉发送消息成功");
}
@Test
public void velocityTest() {
String[] toArr = new String[]{"15734078927"};
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("line",System.lineSeparator());
dataMap.put("title","你叫什么名称");
dataMap.put("content","我叫岳泽霖,是一个快乐的程序员");
dingService.sendVelocityText("md消息",toArr, dataMap,"interface_tenwhy.vm");
log.info(">>>发送测试钉钉成功");
}
}
本章节的代码放置在 github 上:
https://github.com/yuejianli/springboot/tree/develop/SpringBoot_Dingding
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!