导读:本期聚焦于椎名光创作的《Spring Boot 如何整合企业微信 API 实现内部系统通知推送?》,敬请观看详情。企业内部系统往往需要及时把告警、审批、订单等消息推送给员工,企业微信的机器人接口和应用消息接口是实现这类通知的常用方案。本文将围绕 Spring Boot 环境讲解如何封装企业微信 API 调用,内容涵盖机器人 Webhook 群通知、access_token 的获取与缓存刷新、应用消息接口的认证与发送流程,同时给出统一通知服务的代码设计与异常重试处理思路,帮助开发者快速搭建一套稳定可靠的企业内部通知推送能力。

企业内部的运维告警、审批提醒、订单异常通知,如果只靠邮件推送,时效性往往跟不上。企业微信作为很多公司的内部沟通工具,其开放的 API 可以让业务系统直接把消息推送到员工手机上,几乎零延迟。本文将介绍如何在 Spring Boot 项目中整合企业微信 API,从最简单的群机器人 Webhook,到需要认证的应用消息接口,逐步实现一套可复用的内部通知服务。

Spring Boot 如何整合企业微信 API 实现内部系统通知推送?

一、方案选型:群机器人还是自建应用

企业微信提供了两种主流的消息推送方式,理解它们的区别是做技术选型的第一步。

第一种是群机器人 Webhook。在企业微信群里添加机器人后,会得到一个 Webhook 地址,任何人拿到这个地址都可以直接 POST JSON 数据发消息,不需要 access_token,不需要回调配置。这种方式实现成本最低,适合往固定的运维群、告警群推送通知。缺点是无法精确指定某个人,只能发到群内,且消息格式有一定限制。

第二种是自建应用消息接口。在企业微信管理后台创建一个自建应用后,通过 corpid、corpsecret 换取 access_token,再调用消息接口,可以精确推送给某个成员、某个部门或者全体人员,还支持文本、卡片、Markdown、小程序通知等多种消息类型。这种方式适合做真正的系统级通知,比如审批待办、账单提醒等场景。

实际项目中两者常常组合使用:告警类广播走机器人,点对点通知走自建应用。下面的实现会把两者统一封装成一个 WecomNotifyService,业务方调用时无需关心底层用的是哪种通道。

二、群机器人 Webhook 推送实现

机器人推送本质上就是一个 HTTP POST 请求,用 Spring 自带的 RestTemplate 或者 WebClient 都可以完成。建议把 Webhook 地址配置在 application.yml 中,方便区分测试群和生产群。

先看配置文件:

wecom:
  robot:
    webhook: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxxxxx-xxxx-xxxx

然后用 @ConfigurationProperties 接收配置,并封装发送方法。这里以文本消息和 Markdown 消息为例:

@Component
@ConfigurationProperties(prefix = "wecom.robot")
public class WecomRobotClient {

    private String webhook;

    public void setWebhook(String webhook) {
        this.webhook = webhook;
    }

    private final RestTemplate restTemplate = new RestTemplate();

    /**
     * 发送文本消息,可@指定成员
     */
    public void sendText(String content, List<String> mentionedList) {
        Map<String, Object> body = new HashMap<>();
        body.put("msgtype", "text");
        Map<String, Object> text = new HashMap<>();
        text.put("content", content);
        if (mentionedList != null && !mentionedList.isEmpty()) {
            text.put("mentioned_list", mentionedList);
        }
        body.put("text", text);
        post(body);
    }

    /**
     * 发送Markdown消息
     */
    public void sendMarkdown(String markdown) {
        Map<String, Object> body = new HashMap<>();
        body.put("msgtype", "markdown");
        Map<String, Object> md = new HashMap<>();
        md.put("content", markdown);
        body.put("markdown", md);
        post(body);
    }

    private void post(Map<String, Object> body) {
        Map<String, Object> resp = restTemplate.postForObject(webhook, body, Map.class);
        System.out.println("机器人响应: " + resp);
    }
}

有几个细节值得注意。机器人接口有频率限制,每个机器人每分钟最多发 20 条消息,超频会返回错误码 45009,所以告警风暴场景下要做本地限流或者合并告警内容。另外 Markdown 消息支持的语法子集很有限,标题、加粗、链接、引用可用,表格和图片是不可用的,写模板时不要照搬标准 Markdown。

三、自建应用消息:access_token 获取与缓存

自建应用接口的第一步是用 corpid 和 corpsecret 换取 access_token,这个 token 有效期是 7200 秒。企业微信官方明确要求应用需要缓存并定期刷新 token,而不是每次发消息都去请求一次,否则频繁获取会触发限流。

单机场景下可以用一个带过期时间的内存缓存,集群部署时建议放到 Redis 里,用分布式锁避免多个实例同时刷新。下面是一个基于内存的简洁实现,思路同样适用于 Redis:

@Component
public class WecomTokenManager {

    @Value("${wecom.corp.id}")
    private String corpId;

    @Value("${wecom.corp.secret}")
    private String corpSecret;

    private final RestTemplate restTemplate = new RestTemplate();

    // 缓存的token和过期时间
    private volatile String accessToken;
    private volatile long expireAt = 0;

    public synchronized String getToken() {
        // 提前5分钟过期,避免边界问题
        if (accessToken == null || System.currentTimeMillis() > expireAt - 300_000) {
            refresh();
        }
        return accessToken;
    }

    private void refresh() {
        String url = String.format(
            "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s",
            corpId, corpSecret);
        Map<String, Object> resp = restTemplate.getForObject(url, Map.class);
        if (resp != null && Integer.valueOf(0).equals(resp.get("errcode"))) {
            accessToken = (String) resp.get("access_token");
            expireAt = System.currentTimeMillis()
                    + ((Integer) resp.get("expires_in")) * 1000L;
        } else {
            throw new IllegalStateException("获取access_token失败: " + resp);
        }
    }
}

这里把过期判断设计成提前五分钟刷新,是因为请求 token 到实际使用之间有时间差,如果卡着 7200 秒刷新,可能在最后几秒用到已失效的 token。corpsecret 属于敏感信息,不要硬编码在代码里,建议通过环境变量或配置中心注入,并且不要提交到代码仓库。

四、应用消息发送与统一通知服务封装

拿到 token 之后,发送应用消息就是调用 message/send 接口,把接收人的 userid、消息类型和内容组装成 JSON 提交即可:

@Component
public class WecomAppClient {

    private final WecomTokenManager tokenManager;
    private final RestTemplate restTemplate = new RestTemplate();

    public WecomAppClient(WecomTokenManager tokenManager) {
        this.tokenManager = tokenManager;
    }

    public void sendTextToUser(String userId, String content) {
        String token = tokenManager.getToken();
        String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + token;

        Map<String, Object> body = new HashMap<>();
        body.put("touser", userId);
        body.put("msgtype", "text");
        body.put("agentid", 1000002); // 应用agentid,从管理后台查看
        Map<String, Object> text = new HashMap<>();
        text.put("content", content);
        body.put("text", text);

        Map<String, Object> resp = restTemplate.postForObject(url, body, Map.class);
        System.out.println("应用消息响应: " + resp);
    }
}

最后一步是把机器人通道和应用通道收口到一个门面服务里,业务代码只依赖这个门面,后续更换通知渠道时不必改动业务逻辑:

@Service
public class WecomNotifyService {

    private final WecomRobotClient robotClient;
    private final WecomAppClient appClient;

    public WecomNotifyService(WecomRobotClient robotClient, WecomAppClient appClient) {
        this.robotClient = robotClient;
        this.appClient = appClient;
    }

    /**
     * 广播告警:发到运维群
     */
    public void broadcastAlert(String title, String detail) {
        String md = "> **【系统告警】" + title + "**\n> " + detail
                + "\n> 时间: " + java.time.LocalDateTime.now();
        robotClient.sendMarkdown(md);
    }

    /**
     * 个人通知:推送给指定员工
     */
    public void notifyUser(String userId, String content) {
        appClient.sendTextToUser(userId, content);
    }
}

在调用层面再做两件事可以让服务更稳:一是针对 errcode 为 40014(token 失效)和 42001(token 过期)的情况做一次强制刷新重试;二是给通知调用加上异步执行(比如丢给 @Async 线程池),避免企业微信接口抖动阻塞主业务线程。通知本质上属于旁路逻辑,失败了只记日志告警,不应该影响业务事务回滚。

总结一下,机器人 Webhook 适合快速打通群通知,自建应用适合精准触达个人,两者封装成统一服务后,一套代码就能覆盖企业内部绝大部分通知场景。生产环境上线前,记得把限流、token 缓存和失败重试这三块补齐,通知链路基本就不会出问题了。

Spring Boot企业微信API系统通知推送修改时间:2026-09-04 04:00:42

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260904/49996.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。