从头开始,并不意味着失败,相反,正是拥抱成功的第一步,即使还会继续失败
上一章简单介绍了 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", "\n" +
                "**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划"));
        Assert.assertEquals(response.getErrcode().longValue(), 0L);
        log.info(response.toString());
        Thread.sleep(3000);
 
        response = client.sendActionCardMessage("业务报警:This is title", "\n" +
                "**Apple Store** 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
        Assert.assertEquals(response.getErrcode().longValue(), 0L);
        log.info(response.toString());
        Thread.sleep(3000);
 
        response = client.sendActionCardMessage("业务报警:This is title", "\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", "\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", "\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
谢谢您的观看,如果喜欢,请关注我,再次感谢 !!!



















