增加企业微信通知·
parent
1c3dc095e4
commit
251bfe63a6
|
|
@ -16,7 +16,12 @@
|
|||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- 工具类 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.20</version> <!-- 该版本完全兼容JDK 8 -->
|
||||
</dependency>
|
||||
<!-- Spring框架基本的核心工具 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,22 @@
|
|||
package com.agri.common.utils.http;
|
||||
|
||||
import com.agri.common.constant.Constants;
|
||||
import com.agri.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
|
@ -11,17 +28,6 @@ import java.net.URL;
|
|||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.agri.common.constant.Constants;
|
||||
import com.agri.common.utils.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* 通用http发送方法
|
||||
|
|
@ -32,6 +38,69 @@ public class HttpUtils
|
|||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
|
||||
|
||||
// 静态RestTemplate(全局唯一,线程安全)
|
||||
private static final RestTemplate restTemplate;
|
||||
|
||||
// 静态代码块:初始化RestTemplate(项目启动时执行一次)
|
||||
static {
|
||||
// 配置超时时间,避免连接卡死
|
||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||
factory.setConnectTimeout(5000); // 连接超时5秒
|
||||
factory.setReadTimeout(5000); // 读取超时5秒
|
||||
// 初始化静态RestTemplate
|
||||
restTemplate = new RestTemplate(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态通用POST请求(核心方法)
|
||||
* @param url 请求地址
|
||||
* @param requestBody 请求体(实体类/Map/JSON字符串)
|
||||
* @param contentType Content-Type(如application/json)
|
||||
* @param responseType 响应类型(String.class/自定义实体.class)
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T, R> R post(String url, T requestBody, String contentType, Class<R> responseType) {
|
||||
// 前置校验:避免空指针
|
||||
if (url == null || url.isEmpty()) {
|
||||
throw new IllegalArgumentException("请求URL不能为空");
|
||||
}
|
||||
if (contentType == null || contentType.isEmpty()) {
|
||||
throw new IllegalArgumentException("Content-Type不能为空");
|
||||
}
|
||||
if (restTemplate == null) {
|
||||
throw new IllegalStateException("RestTemplate初始化失败,请检查配置");
|
||||
}
|
||||
|
||||
try {
|
||||
// 1. 构建请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType(contentType));
|
||||
|
||||
// 2. 封装请求实体
|
||||
HttpEntity<T> requestEntity = new HttpEntity<>(requestBody, headers);
|
||||
|
||||
// 3. 发送POST请求
|
||||
return restTemplate.postForObject(url, requestEntity, responseType);
|
||||
} catch (RestClientException e) {
|
||||
// 详细异常信息,方便定位问题
|
||||
throw new RuntimeException(
|
||||
String.format("HTTP POST请求失败!url=%s, contentType=%s", url, contentType),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态简化版POST请求(响应默认String)
|
||||
* @param url 请求地址
|
||||
* @param requestBody 请求体
|
||||
* @param contentType Content-Type
|
||||
* @return 字符串响应
|
||||
*/
|
||||
public static <T> String post(String url, T requestBody, String contentType) {
|
||||
return post(url, requestBody, contentType, String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 向指定 URL 发送GET方法的请求
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.agri.common.utils.wechat;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import com.agri.common.utils.http.HttpUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Auther: jone
|
||||
* @Date: 2026/1/24 - 01 - 24 - 21:12
|
||||
* @Description: com.agri.common.utils.wechat
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class WxUtil {
|
||||
|
||||
|
||||
private static final String WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=3cfeb466-76b9-4cf9-b03b-2324a2c3900f";
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
public static Map pushText(String param) {
|
||||
// 1. 构建请求参数
|
||||
Map<String, Object> requestBody = MapUtil.<String, Object>builder()
|
||||
.put("msgtype", "text")
|
||||
.put("text", MapUtil.<String, Object>builder()
|
||||
.put("content", param)
|
||||
.build())
|
||||
.build();
|
||||
return HttpUtils.post(WEBHOOK_URL,
|
||||
requestBody, MediaType.APPLICATION_JSON_VALUE, Map.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.agri.framework.config;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration // 必须加
|
||||
public class RestTemplateConfig {
|
||||
@Bean // 必须加,声明RestTemplate为Spring Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.agri.framework.manager;
|
||||
|
||||
import com.agri.common.utils.wechat.WxUtil;
|
||||
import com.agri.framework.config.MqttConfig;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
|
|
@ -174,6 +175,7 @@ public class MqttAutoOffManager {
|
|||
try {
|
||||
runAutoOff(deviceId, funcType);
|
||||
} catch (Exception e) {
|
||||
WxUtil.pushText("【自动关任务】提交任务失败! deviceId: "+deviceId+", funcType: "+funcType+", msg: "+e.getMessage());
|
||||
log.error("【自动关任务】执行失败,deviceId={}, funcType={}", deviceId, funcType, e);
|
||||
} finally {
|
||||
// 任务执行完成后移除映射
|
||||
|
|
@ -205,6 +207,7 @@ public class MqttAutoOffManager {
|
|||
try {
|
||||
latestObj = JSON.parseObject(latest);
|
||||
} catch (Exception e) {
|
||||
WxUtil.pushText("自动关任务执行报错-解析异常:deviceId:" + deviceId + ", funcType:" + funcType+"异常:"+e.getMessage());
|
||||
log.warn("【自动关任务】最新状态JSON解析失败,跳过:deviceId={}, funcType={}", deviceId, funcType);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.agri.framework.manager;
|
||||
|
||||
import com.agri.common.utils.wechat.WxUtil;
|
||||
import com.agri.framework.web.dispatcher.MqttMessageDispatcher;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
|
||||
|
|
@ -139,7 +140,7 @@ public class MqttClientManager implements SmartLifecycle {
|
|||
|
||||
log.error("【MQTT连接异常】连接断开,clientId:{},原因:{}",
|
||||
safeClientId(), (cause == null ? "unknown" : cause.getMessage()), cause);
|
||||
|
||||
WxUtil.pushText("【MQTT连接异常】连接断开,clientId:"+safeClientId()+",原因:"+(cause == null ? "unknown" : cause.getMessage()));
|
||||
// 【方案A】不再触发自写重连;Paho自动重连会接管重连过程
|
||||
// 这里只记录日志即可
|
||||
if (isRunning.get()) {
|
||||
|
|
@ -166,6 +167,9 @@ public class MqttClientManager implements SmartLifecycle {
|
|||
log.debug("mqttBizPool active={}, queue={}",
|
||||
mqttBizPool.getActiveCount(),
|
||||
mqttBizPool.getQueue().size());
|
||||
if (mqttBizPool.getActiveCount()>10 || mqttBizPool.getQueue().size()>1000) {
|
||||
WxUtil.pushText("线程池繁忙 正在处理中任务:"+mqttBizPool.getActiveCount()+", 剩余待进行任务:"+mqttBizPool.getQueue().size());
|
||||
}
|
||||
try {
|
||||
// 优化:显式指定UTF-8编码,避免乱码(JDK 8兼容)
|
||||
mqttMessageDispatcher.handleMessage(topic, payload);
|
||||
|
|
|
|||
|
|
@ -47,12 +47,6 @@
|
|||
<version>3.5.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.8.20</version> <!-- 该版本完全兼容JDK 8 -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
|
|
|||
Loading…
Reference in New Issue