From 251bfe63a61e297d42c8b24540c99eee9ea3e69d Mon Sep 17 00:00:00 2001 From: xce Date: Sat, 24 Jan 2026 21:53:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E9=80=9A=E7=9F=A5=C2=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agri-common/pom.xml | 7 +- .../com/agri/common/utils/http/HttpUtils.java | 91 ++++++++++++++++--- .../com/agri/common/utils/wechat/WxUtil.java | 36 ++++++++ .../framework/config/RestTemplateConfig.java | 12 +++ .../framework/manager/MqttAutoOffManager.java | 3 + .../framework/manager/MqttClientManager.java | 6 +- agri-generator/pom.xml | 6 -- 7 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 agri-common/src/main/java/com/agri/common/utils/wechat/WxUtil.java create mode 100644 agri-framework/src/main/java/com/agri/framework/config/RestTemplateConfig.java diff --git a/agri-common/pom.xml b/agri-common/pom.xml index 5034cd1..271410c 100644 --- a/agri-common/pom.xml +++ b/agri-common/pom.xml @@ -16,7 +16,12 @@ - + + + cn.hutool + hutool-all + 5.8.20 + org.springframework diff --git a/agri-common/src/main/java/com/agri/common/utils/http/HttpUtils.java b/agri-common/src/main/java/com/agri/common/utils/http/HttpUtils.java index 97045fd..529cd32 100644 --- a/agri-common/src/main/java/com/agri/common/utils/http/HttpUtils.java +++ b/agri-common/src/main/java/com/agri/common/utils/http/HttpUtils.java @@ -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 R post(String url, T requestBody, String contentType, Class 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 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 String post(String url, T requestBody, String contentType) { + return post(url, requestBody, contentType, String.class); + } + /** * 向指定 URL 发送GET方法的请求 * diff --git a/agri-common/src/main/java/com/agri/common/utils/wechat/WxUtil.java b/agri-common/src/main/java/com/agri/common/utils/wechat/WxUtil.java new file mode 100644 index 0000000..1c7954b --- /dev/null +++ b/agri-common/src/main/java/com/agri/common/utils/wechat/WxUtil.java @@ -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 requestBody = MapUtil.builder() + .put("msgtype", "text") + .put("text", MapUtil.builder() + .put("content", param) + .build()) + .build(); + return HttpUtils.post(WEBHOOK_URL, + requestBody, MediaType.APPLICATION_JSON_VALUE, Map.class); + } +} diff --git a/agri-framework/src/main/java/com/agri/framework/config/RestTemplateConfig.java b/agri-framework/src/main/java/com/agri/framework/config/RestTemplateConfig.java new file mode 100644 index 0000000..395602f --- /dev/null +++ b/agri-framework/src/main/java/com/agri/framework/config/RestTemplateConfig.java @@ -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(); + } +} \ No newline at end of file diff --git a/agri-framework/src/main/java/com/agri/framework/manager/MqttAutoOffManager.java b/agri-framework/src/main/java/com/agri/framework/manager/MqttAutoOffManager.java index 48ff9c8..cd030de 100644 --- a/agri-framework/src/main/java/com/agri/framework/manager/MqttAutoOffManager.java +++ b/agri-framework/src/main/java/com/agri/framework/manager/MqttAutoOffManager.java @@ -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; } diff --git a/agri-framework/src/main/java/com/agri/framework/manager/MqttClientManager.java b/agri-framework/src/main/java/com/agri/framework/manager/MqttClientManager.java index ab41a3a..18852fb 100644 --- a/agri-framework/src/main/java/com/agri/framework/manager/MqttClientManager.java +++ b/agri-framework/src/main/java/com/agri/framework/manager/MqttClientManager.java @@ -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); diff --git a/agri-generator/pom.xml b/agri-generator/pom.xml index 72c94c4..a3207fe 100644 --- a/agri-generator/pom.xml +++ b/agri-generator/pom.xml @@ -47,12 +47,6 @@ 3.5.3.1 - - - cn.hutool - hutool-all - 5.8.20 - org.projectlombok lombok