CARVIEW |
Select Language
HTTP/2 200
date: Wed, 23 Jul 2025 23:43:35 GMT
content-type: text/html; charset=utf-8
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
x-robots-tag: none
etag: W/"c7236261ca07a861e4490083b122fda9"
cache-control: max-age=0, private, must-revalidate
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
content-encoding: gzip
accept-ranges: bytes
set-cookie: _gh_sess=aFTcLPJGLY1V16Jrc%2FaQrgyMpBSsqMVW0JPztHWux8iIeimOkD2zHiSJYPoxoAs5utk4Ho7xmaC1wguwYJTEYcztyMvt9JARgc5py2QIZDbOBBwKt5%2FdtxeP034yjSdwy1q%2FVDxWXaYgNggvIbgdEeie7677sJnEKsUCiAxC%2BlGZwjYe4Qy%2FeZ0eguGhDSI5odpHCwg6eVqOe52I0CMlT8TVssqNmsXEeAyVPqpsbj2jJy7vWRt3ZcMx7EnCdN%2FhI%2F%2F%2BXUW0IrE8IJP%2FC0W7UQ%3D%3D--Mufbjc3TWd%2BrJkGd--gTllxRcOqBhqQYXCDY7ZCA%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.45067969.1753314215; Path=/; Domain=github.com; Expires=Thu, 23 Jul 2026 23:43:35 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Thu, 23 Jul 2026 23:43:35 GMT; HttpOnly; Secure; SameSite=Lax
x-github-request-id: 9740:EE750:19E570:24073D:688173A7
Docs for DingTalk 1.x · AnswerAIL/dingtalk-spring-boot-starter Wiki · GitHub
Skip to content
Navigation Menu
{{ message }}
-
Notifications
You must be signed in to change notification settings - Fork 80
Docs for DingTalk 1.x
Jaemon edited this page Nov 26, 2020
·
2 revisions
- JDK1.8
- springboot版本: 2.0.3.RELEASE
<dependency>
<groupId>com.github.answerail</groupId>
<artifactId>dingtalk-spring-boot-starter</artifactId>
<version>3.0.0-RELEASE</version>
</dependency>
spring:
dingtalk:
# dingtalk功能开关
enabled: true
# 项目id, 推荐值: ${spring.application.name}
project-id: ${spring.application.name}
token-id: c60d4824e0ba4a30544e81212256789331d68b0085ed1a5b2279715741355fbc
# 自定义关键字, 仅支持text和markdown消息类型
title: 消息推送
# 签名秘钥
secret: APC3eb471b2761851d6ddd1abcndf2d97be21447d8818f1231c5ed61234as52d1w0
# 是否异步执行
async: true
# 服务状态监控通知开关
monitor:
# 服务启动成功通知
success: true
# 服务退出通知, 注意: kill -9 <PID>不会触发通知
exit: false
# 服务启动失败通知
falied: false
# 异步处理线程池参数配置, 可选
# executor-pool:
# http客户端配置(优先使用项目中已有的), 可选
# ok-http:
- enabled: 选填, 是否启用dingtalk功能开关
- token-id: 必填, 获取方式
- project-id: 必填, 项目名称。 建议: 可以用 project-id 作为 钉钉机器人设置安全策略-自定义关键词(自定义关键词有长度限制,可自行截取前缀或后缀)
- title: 选填。 默认值(通知)
- secret: 选填, 需要签名时必填, 获取方式
- async: 选填, true | false(默认)
- monitor: 选填,默认值(false)
- decrypt: 选填, 是否需要对tokenId进行加密(默认false)
- decryptKey: 选填, tokenId解密秘钥, decrypt为true时必填, 获取方式有以下两种
- java -jar dingtalk-spring-boot-starter-[1.0.5]-RELEASE.jar [tokenId]
- ConfigTools.encrypt(tokenId);
- dinger-locations: 选填, 定义 XXXDinger.xml 文件存放路径(使用xml方式定义消息体时则必填)
public class Demo {
@Autowired
private DingTalkSender dingTalkSender;
public void test() {
// text类型
dingTalkSender.send(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");
// text类型带@
dingTalkSender.send(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。", Lists.newArrayList("135XXXXXXXX"));
// text类型带全部
dingTalkSender.sendAll(MsgTypeEnum.TEXT, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");
// markdown类型
dingTalkSender.send(MsgTypeEnum.MARKDOWN, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。");
// markdown类型带@
dingTalkSender.send(MsgTypeEnum.MARKDOWN, "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM", "服务启动通知", "服务启动异常啦。。。", Lists.newArrayList("135XXXXXXXX"));
}
}
markdown消息体暂时不支持@全部
public class Demo {
@Autowired
private DingTalkSender dingTalkSender;
// 整体跳转ActionCard类型
public void singleActionCardReq() {
String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
SingleActionCardReq actionCardReq = new SingleActionCardReq();
SingleActionCardReq.SingleActionCard actionCard = new SingleActionCardReq.SingleActionCard();
actionCardReq.setActionCard(actionCard);
actionCard.setTitle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身");
actionCard.setText("\" \n" +
" ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
" Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
actionCard.setBtnOrientation("0");
actionCard.setSingleTitle("阅读全文");
actionCard.setSingleURL("https://github.com/AnswerAIL");
dingTalkSender.send(keyword, actionCardReq);
}
// 独立跳转ActionCard类型
public void actionCardReq() {
String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
ActionCardReq actionCardReq = new ActionCardReq();
ActionCardReq.ActionCard actionCard = new ActionCardReq.ActionCard();
actionCardReq.setActionCard(actionCard);
actionCard.setTitle("乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身");
actionCard.setText(" \n" +
" ### 乔布斯 20 年前想打造的苹果咖啡厅 \n" +
" Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划");
actionCard.setBtnOrientation("0");
List<ActionCardReq.ActionCard.Button> buttons = Lists.newArrayList();
actionCard.setBtns(buttons);
buttons.add(new ActionCardReq.ActionCard.Button("内容不错", "https://github.com/AnswerAIL"));
buttons.add(new ActionCardReq.ActionCard.Button("不感兴趣", "https://github.com/AnswerAIL"));
dingTalkSender.send(keyword, actionCardReq);
}
// FeedCard类型
public void feedCardReq() {
String keyword = "DYZ3AALTRBD2AIDLL0Y3EQ4TYGLJDUM";
FeedCardReq feedCardReq = new FeedCardReq();
FeedCardReq.FeedCard feedCard = new FeedCardReq.FeedCard();
feedCardReq.setFeedCard(feedCard);
List<FeedCardReq.FeedCard.Link> links = Lists.newArrayList();
feedCard.setLinks(links);
links.add(new FeedCardReq.FeedCard.Link("时代的火车向前开1", "https://github.com/AnswerAIL", "https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png"));
links.add(new FeedCardReq.FeedCard.Link("时代的火车向前开2", "https://github.com/AnswerAIL", "https://gw.alicdn.com/tfs/TB1ut3xxbsrBKNjSZFpXXcXhFXa-846-786.png"));
dingTalkSender.send(keyword, feedCardReq);
}
}
@Configuration
public class MyConfiguration extends DingTalkConfigurerAdapter {
@Override
public void configure(DingTalkManagerBuilder config) throws Exception {
// ...
}
}
@Configuration
public class MyConfiguration {
// 自定义text类型消息体
@Bean
public CustomMessage textMessage() {
return (dingTalkProperties, subTitle, keyword, content, phones) -> {
String message = null;
// ...
return message;
};
}
// 自定义markdown类型消息体
@Bean
public CustomMessage markDownMessage() {
return (dingTalkProperties, subTitle, keyword, content, phones) -> {
String message = null;
// ...
return message;
};
}
}
仅支持text和markdown消息类型
@Configuration
public class MyConfiguration {
// 自定义异常回调函数
@Bean
public Notice notice() {
return (dkExCallable) -> {
// ...
};
}
}
- 更改前: URL_PREV&sign=XXX×tamp=XXX
- 更改后: URL_PREV×tamp=XXX&sign=XXX
@Data
@AllArgsConstructor
public class SignDTO extends SignBase {
private String sign;
private Long timestamp;
@Override
public String transfer() {
StringBuilder signStr = new StringBuilder(SEPERATOR);
signStr
.append("timestamp=").append(this.timestamp).append(SEPERATOR)
.append("sign=").append(this.sign);
return signStr.toString();
}
}
@Configuration
public class MyConfiguration {
@Bean
public DkSignAlgorithm<SignDTO> dkSignAlgorithm() {
return new DkSignAlgorithm<SignDTO>() {
@Override
public SignDTO sign(String secret) throws Exception {
Long timestamp = System.currentTimeMillis();
// TODO 使用默认算法, 如果后期算法改变, 可在此更变签名算法
String sign = algorithm(timestamp, secret);
return new SignDTO(sign, timestamp);
}
};
}
}
该功能只针对后期版本变更进行扩展, 当前版本没有使用的必要
@Configuration
public class MyConfiguration {
@Bean
public DkIdGenerator dkIdGenerator() {
return () -> {
String dkid = null;
// ...
return dkid;
};
}
}
注意ID最好保证全局唯一,
同步调用直接返回响应结果,异步操作返回处理id(dkid)
。
@Configuration
public class MyConfiguration {
@Bean
public DkCallable dkCallable() {
return (dkid, result) -> {
// ...
};
}
}
此处方法形参(dkid, result),其中: dkid也就是异步通知的返回结果, result为请求实际的响应报文字符串。
@Configuration
public class MyConfiguration {
@Bean
public Executor dingTalkExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// ...
return executor;
}
}
注意开启异步处理时使用内置线程池, 如果项目中有定义其他线程池配置, 注入线程池对象时请指定线程池名称。 如:
@Qualifier("executor")
@Configuration
public class MyConfiguration {
@Bean
public OkHttpClient okHttpClient() {
// ...
}
}
服务状态通知需艾特所有人
@Configuration
public class MyConfiguration {
@Bean
public Notification notification() {
return new DefaultApplicationEventNotification() {
@Override
public MsgType message(String text) {
TextReq message = (TextReq) super.message(text);
Message.At at = new Message.At();
at.setIsAtAll(true);
message.setAt(at);
return message;
}
};
}
}
服务状态通知只需启动失败时艾特所有人,其他情况不艾特
@Configuration
public class MyConfiguration {
@Bean
public Notification notification() {
return new DefaultApplicationEventNotification() {
@Override
public MsgType failed(ApplicationFailedEvent event, String projectId) {
TextReq message = (TextReq) super.failed(event, projectId);
Message.At at = new Message.At();
at.setIsAtAll(true);
message.setAt(at);
return message;
}
};
}
}
服务状态通知需自定义消息内容
@Configuration
public class MyConfiguration {
@Bean
public Notification notification() {
return new Notification() {
@Override
public String successMessage(ApplicationReadyEvent event, String projectId) {
String message = null;
// TODO ...
return message;
}
@Override
public String failedMessage(ApplicationFailedEvent event, String projectId) {
String message = null;
// TODO ...
return message;
}
@Override
public String exitMessage(ContextClosedEvent event, String projectId) {
String message = null;
// TODO ...
return message;
}
};
}
}
Clone this wiki locally
You can’t perform that action at this time.