作者: Mintimate
博客: https://www.mintimate.cn/
Mintimate's Blog, 只为与你分享
封面嗷
前言
消息推送到团队微信, 很多人看了标题, 可能不能理解什么意思, 其实:
消息: 工程项目内的提示消息, 比如: 项目关联的 OCR 识别次数接口告罄通知, 项目均衡过载通知等消息.
团队微信: 企业微信或关联企业微信的个人微信, 用于接受消息.
通过上述描述, 大家是不是就更能理解了呢? 所以, 我们项目 "说话", 就是让我们 Java 项目日常使用过程中, 一些时间触发时, 使用 API 推送消息至开发者 / 团队的微信, 方便团队维护. 类似邮件提醒.
本文推送是直接内置到 Java 项目内, 如: Springboot 项目后端. 如果需单独搭建推送服务, 给其他工程使用, 可以使用 PHP 进行搭建:
[web Function] 实战使用: PHP Web 函数搭建推送服务, 轻松推送消息至个人微信
推送服务
具体来说, 推送服务的思路是这样的:
推送服务逻辑
实际的项目中, 也可以使用:
场景 1:API 服务告罄警告
有时候, 我们搭建一些项目, 会直接使用外部 API 除了图片. 比如: 使用腾讯云万象数据, 识别图片分类
识别图片分类
这样的接口, 肯定是有使用次数限制, 在次数快使用完毕, 就可以创建一个方法, 直接调用实现写好的工具包方法, 对微信发送消息:
API 使用告罄提醒
场景 2: 数据库 "灾变"
Java 作为一门后端语言, 数据库的重要性不用多说. 如果数据库服务器崩溃了, 肯定是要第一时间处理. 我们可以写一个监听, 来观察数据库的 "存活":
数据库 "灾变" 提醒
前期准备
前期准备很简单, 主要是
Java 依赖包: Fastjson https://github.com/alibaba/fastjson ,springframework-Web https://spring.io/projects/spring-framework
微信推送接口申请
Java 依赖包
1. Fastjson 包
在 Maven 内, 加入 Fastjson 的包:
添加 Fastjson 包
- <!--Fastjson Alibaba-->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.75</version>
- </dependency>
如果你项目并没有使用 Maven 进行项目包管理, 需要手动下载 Fastjson, 并添加至项目依赖内:
Fastjson 项目发布地址 https://github.com/alibaba/fastjson
使用 Fastjson, 主要是用于处理 JSON 对象. 比如: JSON 对象封装, JSON 和 String 互转以及 JSON 对象解析等.
2. springframework
直接应用 springframework 的包, 主要是想偷懒...... 如果你有更简单的方法实现包含 header 的 HTTP 请求, 也可以不用 springframework 的包:
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-Web</artifactId>
- <version>5.3.3</version>
- </dependency>
微信推送接口申请
微信接口申请, 实际上是申请企业微信的接口. 但是个人也可以申请.(且后期可以选择推过微信接收推送, 实际上不需要多下载安装一个企业微信在手机上.)
1. 应用创建
进入企业微信 https://work.weixin.qq.com/ 官网, 注册一个企业微信. 创建好后. 我们选择应用管理, 并创建一个应用:
创建应用
2. 获取 AgentId 和 Secret
创建好后, 我们获取应用 AgentId 和 Secret:
获取 AgentId 和 Secret
3. 获取企业 ID
进入我的企业页面, 拉到最下边, 可以看到企业 ID:
企业 ID
4. 绑定个人微信
如果你并不想保留企业微信在手机上, 想直接推送消息到自己的个人微信, 可以进入「我的企业」 → 「微信插件」, 拉到下边扫描二维码, 关注以后即可收到推送的消息:
绑定个人微信
通讯原理
综上, 你应该在项目内添加了 Fastjson, 并申请微信接口, 得到参数:
WECOM_CID: 上文步骤中获取的企业 ID
WECOM_SECRET: 上文步骤中获取的应用 Secret
AGENT_ID: 上文步骤中获取的应用 AgentId
之所以需要上述消息, 主要是用于 token 的生成, 可以看微信开发者文档:
企业微信开发 API
开发文档
而有了 token, 才可以对微信进行推送. 进一步, 系统工作时候的原理:
系统工作原理
代码实现
1. 静态属性
我们创建了一个工具类, 因为实际使用, 肯定是作为一个静态方法使用, 不用实例对象. 所以, 我们创建静态方法:
- // 微信接口获取
- final static String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
- // 个人企业微信接口参数
- final static String SEND_MESSAGE_URL = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=";
- // 企业微信公司 ID
- final static String WECOM_CID = "";
- // 企业微信公司密钥
- final static String WECOM_SECRET = "";
- // 应用 ID
- final static String AGENT_ID = "";
- // 发送用户,@all 代表企业微信里所有人
- final static String TOUSER = "@all";
- // 发送失败
- final static int ERROR_CODE=0;
- // 发送成功
- final static int SUCCESS_CODE=0;
- // 发送状态
- static int STATUS_CODE=ERROR_CODE;
当然, 我这边的状态写的可能比较少, 所以只写了 2 个状态. 大家后续可以自行更改. 另外大家记得填入自己企业微信的 WECOM_CID,WECOM_SECRET,AGENT_ID.
2. Token 申请
静态方法内, 我已经提前定义 Token 申请的地址, 我们只需要封装参数为 JSON, 对其请求即可:
- // 微信接口获取
- final static String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
我们使用 RestTemplate 发起 HTTP 请求, 先定义一个通用包, 用于后续复用:
- // HTTP 请求发送
- private static String HttpRestClient(String url, HttpMethod method, JSONObject JSON) throws IOException {
- SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
- requestFactory.setConnectTimeout(10 * 1000);
- requestFactory.setReadTimeout(10 * 1000);
- RestTemplate client = new RestTemplate(requestFactory);
- HttpHeaders headers = new HttpHeaders();
- MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
- headers.setContentType(type);
- HttpEntity<String> requestEntity = new HttpEntity(JSON.toString(), headers);
- // 执行 HTTP 请求
- ResponseEntity<String> response = client.exchange(url, method, requestEntity, String.class);
- return response.getBody();
- }
之后, 写一个方法对其调用:
- private static int sendMessage(String sendText, String access_token) {
- String url = SEND_MESSAGE_URL + access_token;
- HttpMethod method = HttpMethod.POST;
- JSONObject JSON = new JSONObject();
- JSONObject jsonText = new JSONObject();
- jsonText.put("content", sendText);
- JSON.put("touser", TOUSER);
- JSON.put("agentid", AGENT_ID);
- JSON.put("msgtype", "text");
- JSON.put("text", jsonText);
- // 发送 http 请求并返回结果
- try {
- String result = sendMessageToWechat.HttpRestClient(url, method, JSON);
- JSONObject obj = JSON.parseObject(result);
- // 将 JSON 字符串转化为 JSON 对象
- if ((int) obj.get("errcode") == 200) {
- // 从 JSON 对象中提取键值为 "status" 的键值对, 并将键值保存在 "status" 字符串中
- STATUS_CODE = SUCCESS_CODE;
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- return STATUS_CODE;
- }
测试一下:
获取 Token 成功
3. 携带 Token 发送消息
首先, 创建一个私有方法, 对 Token 和 SEND_MESSAGE_URL(https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=) 组合的链接, 发送 content 对象. 而这个 content 需要和其他参数组合为 JSON 对象, 其结构:
JSON 对象结构
用 Fastjson 来组合 JSON 对象很简单:
- JSONObject JSON = new JSONObject();
- JSONObject jsonText = new JSONObject();
- jsonText.put("content", sendText);
- JSON.put("touser", TOUSER);
- JSON.put("agentid", AGENT_ID);
- JSON.put("msgtype", "text");
- JSON.put("text", jsonText);
用上问提到的方法, 再次发送 POST 请求即可:
- private static int sendMessage(String sendText, String access_token) {
- String url = SEND_MESSAGE_URL + access_token;
- HttpMethod method = HttpMethod.POST;
- JSONObject JSON = new JSONObject();
- JSONObject jsonText = new JSONObject();
- jsonText.put("content", sendText);
- JSON.put("touser", TOUSER);
- JSON.put("agentid", AGENT_ID);
- JSON.put("msgtype", "text");
- JSON.put("text", jsonText);
- // 发送 http 请求并返回结果
- try {
- String result = sendMessageToWechat.HttpRestClient(url, method, JSON);
- JSONObject obj = JSON.parseObject(result);
- // 将 JSON 字符串转化为 JSON 对象
- if ((int) obj.get("errcode") == 200) {
- // 从 JSON 对象中提取键值为 "status" 的键值对, 并将键值保存在 "status" 字符串中
- STATUS_CODE = SUCCESS_CODE;
- }
- }
- catch (IOException e) {
- e.printStackTrace();
- }
- return STATUS_CODE;
- }
理论上, 这个方法执行成功, 消息就可以直接发送了. 但是, 这个未来作为系统的工具包, 不用去实例, 我们再写一个方法封装一下:
- public static int sendText(String Text) {
- if (Text == null) {
- return ERROR_CODE;
- }
- String access_token = getAccessToken();
- if (access_token == null || access_token.equals("")) {
- return ERROR_CODE;
- } else {
- sendMessage(Text, access_token);
- }
- return STATUS_CODE;
- }
这样, Controller 层, 就可以直接调用该方法了.
测试使用
最后, 我们测试使用一下. 为了方便, 我就不用 Test 类去测试, 直接使用 Main 方法去测试:
- public static void main(String args[]) {
- sendMessageToWechat.sendText("Mintimate's Blogn" +
- "只为与你分享~\n" +
- "=> Bilibili:https://space.bilibili.com/355567627\n"+
- "=> 腾讯云社区: https://cloud.tencent.com/developer/user/7704194\n"+
- "=====\n"+
- "<a href='https://www.mintimate.cn'> 查看更多 </a>");
- }
测试代码
运行, 即可以看到微信收到通知了:
微信上收到消息
样例代码
有些小伙伴可能想要文中的样例代码, 为此我也在 GitHub 上进行了开源:
https://github.com/Mintimate/WeChatPushJava
完善思路
这样的推送服务是可以完善的. 比如:
Redis 存储 Token
如果你有看企业微信开发者文档, 你会发现 Token 的有效期是: 1800 秒. 你可以使用 Redis 进行临时存储缓存.
发送图片
本文演示发送消息, 但是接口是可以发送图片, 语言等内容. 且接受数据均为 JSON, 可以按本文方法实现:
图片消息
卡片消息
PHP 接口
使用 Java, 直接集成在 JavaWeb 项目里, 固然不错, 但是如果想作为一个 API 接口, 那么使用 PHP 是更好的选择, 还可以使用 Serverless:
PHP Web 函数搭建推送服务, 轻松推送消息至个人微信
总结
综上所述, 就是让 Java 项目 "说话" 的方案了嗷. 当然, 肯定有更好的方法, 但是推送到微信, 也觉得是个好方法嗷~
来源: https://www.qcloud.com/developer/article/1850525