From b28b1463f70256bfcf4abfb302e86e4c5288056a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=BE=E5=AF=8C=E6=96=8C?= Date: Sat, 27 Sep 2025 20:42:16 +0800 Subject: [PATCH] =?UTF-8?q?feat=20(farm):=20=E8=AE=BE=E5=A4=87=E5=95=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - --- .../service/impl/SoilService.java | 187 ++++----------- .../service/impl/WaterFertilizerService.java | 189 +++------------ .../module/farm/utils/HttpClientUtils.java | 215 ------------------ 3 files changed, 82 insertions(+), 509 deletions(-) delete mode 100644 yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/HttpClientUtils.java diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/SoilService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/SoilService.java index e988d854..1ce89481 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/SoilService.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/SoilService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.impl; +import cn.iocoder.yudao.module.farm.manager.equipmentproducer.conf.DeviceConf; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.DeviceListResponse; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.HistoryDataResponse; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse; @@ -15,6 +16,7 @@ import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime. import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.AbstractDeviceService; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.HistoryDataStorageService; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService; +import cn.iocoder.yudao.module.farm.manager.equipmentproducer.utils.HttpClientUtils; import org.springframework.stereotype.Service; import java.util.*; @@ -29,9 +31,13 @@ import java.util.stream.Collectors; public class SoilService extends AbstractDeviceService { private final HistoryDataStorageService historyDataStorageService; + private final DeviceConf deviceConf; + private final HttpClientUtils httpClientUtils; - public SoilService(HistoryDataStorageService historyDataStorageService) { + public SoilService(HistoryDataStorageService historyDataStorageService, DeviceConf deviceConf, HttpClientUtils httpClientUtils) { this.historyDataStorageService = historyDataStorageService; + this.deviceConf = deviceConf; + this.httpClientUtils = httpClientUtils; } @Override @@ -45,7 +51,7 @@ public class SoilService extends AbstractDeviceService { // 转换请求参数 UserLoginReqVO soilRequest = (UserLoginReqVO) loginRequest; - // TODO: 2025/9/25 调用土壤设备厂商API POST 请求方式 + // 调用土壤设备厂商API POST 请求方式 UserLoginRespVO vendorResponse = callSoilVendorApi(soilRequest); // 转换为统一响应格式 @@ -62,7 +68,7 @@ public class SoilService extends AbstractDeviceService { // 转换请求参数 SysUserDeviceReqVO soilRequest = (SysUserDeviceReqVO) listRequest; - // TODO: 2025/9/25 调用土壤设备厂商API获取设备列表 GET 请求方式 + // 调用土壤设备厂商API获取设备列表 GET 请求方式 SysUserDeviceRespVO vendorResponse = callSoilDeviceListApi(token, soilRequest); // 转换为统一响应格式 @@ -79,7 +85,7 @@ public class SoilService extends AbstractDeviceService { // 转换请求参数 RealTimeDataReqVO soilRequest = (RealTimeDataReqVO) realTimeRequest; - // TODO: 2025/9/26 调用土壤设备厂商API获取实时数据 GET 请求方式 + // 调用土壤设备厂商API获取实时数据 GET 请求方式 RealTimeDataRespVO vendorResponse = callSoilRealTimeDataApi(token, soilRequest); // 直接返回原始响应数据,不进行统一转换 @@ -96,7 +102,7 @@ public class SoilService extends AbstractDeviceService { // 转换请求参数 HistoryDataListPageReqVO soilRequest = (HistoryDataListPageReqVO) historyRequest; - // TODO: 2025/9/26 调用土壤设备厂商API获取历史数据 GET 请求方式 + // T调用土壤设备厂商API获取历史数据 GET 请求方式 HistoryDataListPageRespVO vendorResponse = callSoilHistoryDataApi(token, soilRequest); // TODO: 2025/9/26 模拟保存到MySQL @@ -109,25 +115,13 @@ public class SoilService extends AbstractDeviceService { } } - - - private UserLoginRespVO callSoilVendorApi(UserLoginReqVO request) { - // 模拟调用土壤设备厂商API - // 实际实现中这里会是HTTP请求 - UserLoginRespVO response = new UserLoginRespVO(); - response.setCode("200"); - response.setMessage("成功"); - response.setData(new UserLoginRespVO.VendorData()); - response.getData().setLoginSign("soil-login-sign-" + System.currentTimeMillis()); - response.getData().setCurrDate(System.currentTimeMillis()); - response.getData().setExpDate(System.currentTimeMillis() + 3600000); // 1小时后过期 - response.getData().setToken("soil-token-" + System.currentTimeMillis()); - return response; + String url = deviceConf.getFourSituations().getHosts() + deviceConf.getFourSituations().getGlobal().getUrl21(); + return httpClientUtils.doPost(url, null, request, UserLoginRespVO.class); } private UnifiedLoginResponse convertToUnifiedResponse(UserLoginRespVO vendorResponse) { - if (!"200".equals(vendorResponse.getCode())) { + if (!"1000".equals(vendorResponse.getCode())) { return UnifiedLoginResponse.error(vendorResponse.getMessage()); } @@ -142,34 +136,25 @@ public class SoilService extends AbstractDeviceService { } private SysUserDeviceRespVO callSoilDeviceListApi(String token, SysUserDeviceReqVO request) { - // 模拟调用土壤设备厂商API - SysUserDeviceRespVO response = new SysUserDeviceRespVO(); - response.setCode("200"); - response.setMessage("成功"); + String url = deviceConf.getFourSituations().getHosts() + deviceConf.getFourSituations().getGlobal().getUrl26(); - List deviceList = new ArrayList<>(); + Map headers = new HashMap<>(); +// headers.put("Authorization", "Bearer " + token); + headers.put("token", token); - // 模拟设备数据 - SysUserDeviceRespVO.DeviceInfo device1 = new SysUserDeviceRespVO.DeviceInfo(); - device1.setDeviceAddr("SOIL_001"); - device1.setDeviceName("土壤监测设备1"); - device1.setGroupId("G001"); - device1.setDeviceType("SOIL_MONITOR"); - deviceList.add(device1); + Map params = new HashMap<>(); + if (request.getGroupId() != null) { + params.put("groupId", request.getGroupId()); + } + if (request.getDeviceType() != null) { + params.put("deviceType", request.getDeviceType()); + } - SysUserDeviceRespVO.DeviceInfo device2 = new SysUserDeviceRespVO.DeviceInfo(); - device2.setDeviceAddr("SOIL_002"); - device2.setDeviceName("土壤监测设备2"); - device2.setGroupId("G001"); - device2.setDeviceType("SOIL_MONITOR"); - deviceList.add(device2); - - response.setData(deviceList); - return response; + return httpClientUtils.doGet(url, headers, params, SysUserDeviceRespVO.class); } private DeviceListResponse convertToUnifiedDeviceResponse(SysUserDeviceRespVO vendorResponse) { - if (!"200".equals(vendorResponse.getCode())) { + if (!"1000".equals(vendorResponse.getCode())) { return DeviceListResponse.error(vendorResponse.getMessage()); } @@ -196,114 +181,38 @@ public class SoilService extends AbstractDeviceService { } private RealTimeDataRespVO callSoilRealTimeDataApi(String token, RealTimeDataReqVO request) { - // 模拟调用土壤设备厂商API获取实时数据 - RealTimeDataRespVO response = new RealTimeDataRespVO(); - response.setCode("200"); - response.setMessage("成功"); + String url = deviceConf.getFourSituations().getHosts() + deviceConf.getFourSituations().getGlobal().getUrl28(); - List deviceList = new ArrayList<>(); + Map headers = new HashMap<>(); + headers.put("token", token); +// headers.put("Authorization", "Bearer " + token); - // 模拟设备1的实时数据 - RealTimeDataRespVO.DeviceInfo device1 = new RealTimeDataRespVO.DeviceInfo(); - device1.setDeviceAddr("SOIL_001"); - device1.setDeviceName("土壤监测设备1"); - device1.setLat(39.9093); - device1.setLng(116.3974); - device1.setStatus("在线"); - device1.setDeviceType("SOIL_MONITOR"); - - List realTimeDataList1 = new ArrayList<>(); - - // 节点1数据 - RealTimeDataRespVO.RealTimeData node1 = new RealTimeDataRespVO.RealTimeData(); - node1.setNodeId(1); - node1.setNodeName("土壤温度监测点"); - node1.setNodeType(1); - node1.setTemName("土壤温度"); - node1.setTemUnit("°C"); - node1.setTemValue(25.6); - node1.setTemValueStr("25.6°C"); - node1.setTemAlarmStatus(0); - realTimeDataList1.add(node1); - - // 节点2数据 - RealTimeDataRespVO.RealTimeData node2 = new RealTimeDataRespVO.RealTimeData(); - node2.setNodeId(2); - node2.setNodeName("土壤湿度监测点"); - node2.setNodeType(2); - node2.setHumName("土壤湿度"); - node2.setHumUnit("%"); - node2.setHumValue("65.2"); - node2.setHumValueStr("65.2%"); - node2.setHumAlarmStatus("0"); - realTimeDataList1.add(node2); - - device1.setData(realTimeDataList1); - deviceList.add(device1); - - // 模拟设备2的实时数据(如果请求了多个设备) - if (request.getDeviceAddrs() != null && request.getDeviceAddrs().contains("SOIL_002")) { - RealTimeDataRespVO.DeviceInfo device2 = new RealTimeDataRespVO.DeviceInfo(); - device2.setDeviceAddr("SOIL_002"); - device2.setDeviceName("土壤监测设备2"); - device2.setLat(39.9193); - device2.setLng(116.4074); - device2.setStatus("离线"); - device2.setDeviceType("SOIL_MONITOR"); - - List realTimeDataList2 = new ArrayList<>(); - RealTimeDataRespVO.RealTimeData node3 = new RealTimeDataRespVO.RealTimeData(); - node3.setNodeId(1); - node3.setNodeName("土壤温度监测点"); - node3.setNodeType(1); - node3.setTemName("土壤温度"); - node3.setTemUnit("°C"); - node3.setTemValue(23.1); - node3.setTemValueStr("23.1°C"); - node3.setTemAlarmStatus(0); - realTimeDataList2.add(node3); - - device2.setData(realTimeDataList2); - deviceList.add(device2); + Map params = new HashMap<>(); + if (request.getDeviceAddrs() != null) { + params.put("deviceAddrs", request.getDeviceAddrs()); } - response.setData(deviceList); - return response; + return httpClientUtils.doGet(url, headers, params, RealTimeDataRespVO.class); } private HistoryDataListPageRespVO callSoilHistoryDataApi(String token, HistoryDataListPageReqVO request) { - // 模拟调用土壤设备厂商API获取历史数据 - HistoryDataListPageRespVO response = new HistoryDataListPageRespVO(); + String url = deviceConf.getFourSituations().getHosts() + deviceConf.getFourSituations().getSoil().getUrl44(); - // 设置分页信息 - response.setPages(request.getPages()); - response.setLimit(request.getLimit()); + Map headers = new HashMap<>(); + headers.put("token", token); +// headers.put("Authorization", "Bearer " + token); - // 模拟从厂商API获取的数据 - List rows = generateMockHistoryData( - request.getDeviceAddr(), - Long.parseLong(request.getBeginTime()), - Long.parseLong(request.getEndTime()), - request.getNodeId() - ); - - int total = rows.size(); - int totalPages = (int) Math.ceil((double) total / request.getLimit()); - - // 分页处理 - int fromIndex = (request.getPages() - 1) * request.getLimit(); - int toIndex = Math.min(fromIndex + request.getLimit(), total); - - if (fromIndex >= total) { - response.setRows(new ArrayList<>()); - } else { - response.setRows(rows.subList(fromIndex, toIndex)); + Map params = new HashMap<>(); + params.put("beginTime", request.getBeginTime()); + params.put("endTime", request.getEndTime()); + params.put("deviceAddr", request.getDeviceAddr()); + params.put("pages", request.getPages()); + params.put("limit", request.getLimit()); + if (request.getNodeId() != null) { + params.put("nodeId", request.getNodeId()); } - response.setTotalPages(totalPages); - response.setTotal(total); - - return response; + return httpClientUtils.doGet(url, headers, params, HistoryDataListPageRespVO.class); } private List generateMockHistoryData(String deviceAddr, Long beginTime, Long endTime, String nodeId) { diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/WaterFertilizerService.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/WaterFertilizerService.java index a83df2cc..4258a350 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/WaterFertilizerService.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/manager/equipmentproducer/service/impl/WaterFertilizerService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.impl; +import cn.iocoder.yudao.module.farm.manager.equipmentproducer.conf.DeviceConf; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.DeviceListResponse; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.UnifiedLoginResponse; @@ -14,9 +15,9 @@ import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparam import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.wf.updateparams.UpdateDeviceStatusRespVO; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.AbstractDeviceService; import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService; +import cn.iocoder.yudao.module.farm.manager.equipmentproducer.utils.HttpClientUtils; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -30,6 +31,14 @@ import java.util.stream.Collectors; @Service public class WaterFertilizerService extends AbstractDeviceService { + private final DeviceConf deviceConf; + private final HttpClientUtils httpClientUtils; + + public WaterFertilizerService(DeviceConf deviceConf, HttpClientUtils httpClientUtils) { + this.deviceConf = deviceConf; + this.httpClientUtils = httpClientUtils; + } + @Override public String getDeviceType() { return "water_fertilizer"; @@ -103,23 +112,9 @@ public class WaterFertilizerService extends AbstractDeviceService { } } - - - - - - - - - - private LoginRespVO callWFVendorApi(LoginReqVO request) { - // 模拟调用水肥机设备厂商API - LoginRespVO response = new LoginRespVO(); - response.setCode("200"); - response.setMsg("成功"); - response.setToken("wf-token-" + System.currentTimeMillis()); - return response; + String url = deviceConf.getWaterAndFertilizer().getHosts() + deviceConf.getWaterAndFertilizer().getUrl1(); + return httpClientUtils.doPost(url, null, request, LoginRespVO.class); } private UnifiedLoginResponse convertToUnifiedResponse(LoginRespVO vendorResponse) { @@ -140,33 +135,17 @@ public class WaterFertilizerService extends AbstractDeviceService { } private DevicePageRespVO callWFDeviceListApi(String token, DevicePageReqVO request) { - // 模拟调用水肥机设备厂商API - DevicePageRespVO response = new DevicePageRespVO(); - response.setCode(200); - response.setMsg("成功"); - response.setTotal(2); + String url = deviceConf.getWaterAndFertilizer().getHosts() + deviceConf.getWaterAndFertilizer().getUrl2(); - List rows = new ArrayList<>(); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); - // 模拟设备数据 - DevicePageRespVO.Row row1 = new DevicePageRespVO.Row(); - row1.setDeviceId(1L); - row1.setCode("WF_001"); - row1.setName("水肥机设备1"); - row1.setLng(116.3974); - row1.setLat(39.9093); - rows.add(row1); + Map params = new HashMap<>(); + if (request.getUserCode() != null) { + params.put("userCode", request.getUserCode()); + } - DevicePageRespVO.Row row2 = new DevicePageRespVO.Row(); - row2.setDeviceId(2L); - row2.setCode("WF_002"); - row2.setName("水肥机设备2"); - row2.setLng(116.4074); - row2.setLat(39.9193); - rows.add(row2); - - response.setRows(rows); - return response; + return httpClientUtils.doGet(url, headers, params, DevicePageRespVO.class); } private DeviceListResponse convertToUnifiedDeviceResponse(DevicePageRespVO vendorResponse) { @@ -197,129 +176,29 @@ public class WaterFertilizerService extends AbstractDeviceService { } private RealTimeDeviceDataRespVO callWFRealTimeDataApi(String token, RealTimeDeviceDataReqVO request) { - // 模拟调用水肥机设备厂商API获取实时数据 - RealTimeDeviceDataRespVO response = new RealTimeDeviceDataRespVO(); - response.setDeviceId(request.getDeviceId()); - response.setName("水肥机设备-" + request.getDeviceId()); - response.setStateText("在线"); - response.setStateValue("online"); + String url = deviceConf.getWaterAndFertilizer().getHosts() + deviceConf.getWaterAndFertilizer().getUrl3(); - List controlProperties = new ArrayList<>(); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); - // 模拟控制属性1 - 水泵状态 - RealTimeDeviceDataRespVO.ControlProperty prop1 = new RealTimeDeviceDataRespVO.ControlProperty(); - prop1.setId("pump_switch"); - prop1.setName("水泵开关"); - prop1.setOperateType("switch"); - prop1.setOperateValue("on,off"); - prop1.setValue("on"); - prop1.setFormatValue("开启"); - controlProperties.add(prop1); + Map params = new HashMap<>(); + params.put("deviceId", request.getDeviceId()); - // 模拟控制属性2 - 施肥状态 - RealTimeDeviceDataRespVO.ControlProperty prop2 = new RealTimeDeviceDataRespVO.ControlProperty(); - prop2.setId("fertilizer_switch"); - prop2.setName("施肥开关"); - prop2.setOperateType("switch"); - prop2.setOperateValue("on,off"); - prop2.setValue("off"); - prop2.setFormatValue("关闭"); - controlProperties.add(prop2); - - // 模拟控制属性3 - 流量监测 - RealTimeDeviceDataRespVO.ControlProperty prop3 = new RealTimeDeviceDataRespVO.ControlProperty(); - prop3.setId("flow_rate"); - prop3.setName("水流量"); - prop3.setOperateType("monitor"); - prop3.setOperateValue(""); - prop3.setValue("12.5"); - prop3.setFormatValue("12.5 L/min"); - controlProperties.add(prop3); - - // 模拟控制属性4 - EC值 - RealTimeDeviceDataRespVO.ControlProperty prop4 = new RealTimeDeviceDataRespVO.ControlProperty(); - prop4.setId("ec_value"); - prop4.setName("EC值"); - prop4.setOperateType("monitor"); - prop4.setOperateValue(""); - prop4.setValue("2.1"); - prop4.setFormatValue("2.1 mS/cm"); - controlProperties.add(prop4); - - // 模拟控制属性5 - PH值 - RealTimeDeviceDataRespVO.ControlProperty prop5 = new RealTimeDeviceDataRespVO.ControlProperty(); - prop5.setId("ph_value"); - prop5.setName("PH值"); - prop5.setOperateType("monitor"); - prop5.setOperateValue(""); - prop5.setValue("6.8"); - prop5.setFormatValue("6.8"); - controlProperties.add(prop5); - - response.setControlProperties(controlProperties); - return response; + return httpClientUtils.doGet(url, headers, params, RealTimeDeviceDataRespVO.class); } private UpdateDeviceStatusRespVO callWFUpdateDeviceApi(String token, UpdateDeviceStatusReqVO request) { - // 模拟调用水肥机设备厂商API更新设备属性 - UpdateDeviceStatusRespVO response = new UpdateDeviceStatusRespVO(); + String url = deviceConf.getWaterAndFertilizer().getHosts() + deviceConf.getWaterAndFertilizer().getUrl4(); - // 模拟设备控制逻辑 - String deviceId = request.getDeviceId(); - String switchName = request.getParamStr().getValue1(); - String newValue = request.getParamStr().getValue11(); + Map headers = new HashMap<>(); + headers.put("Authorization", "Bearer " + token); - System.out.println("更新水肥机设备属性 - 设备ID: " + deviceId + - ", 开关名称: " + switchName + ", 新值: " + newValue); + // 构建请求体,包含设备ID和参数 + Map requestBody = new HashMap<>(); + requestBody.put("deviceId", request.getDeviceId()); + requestBody.put("paramStr", request.getParamStr()); - // 模拟不同的控制逻辑 - if ("pump_switch".equals(switchName)) { - if ("on".equals(newValue)) { - System.out.println("水泵开关已开启"); - response.setCode(200); - response.setMsg("水泵开启成功"); - } else if ("off".equals(newValue)) { - System.out.println("水泵开关已关闭"); - response.setCode(200); - response.setMsg("水泵关闭成功"); - } else { - response.setCode(400); - response.setMsg("无效的水泵开关值: " + newValue); - } - } else if ("fertilizer_switch".equals(switchName)) { - if ("on".equals(newValue)) { - System.out.println("施肥开关已开启"); - response.setCode(200); - response.setMsg("施肥开启成功"); - } else if ("off".equals(newValue)) { - System.out.println("施肥开关已关闭"); - response.setCode(200); - response.setMsg("施肥关闭成功"); - } else { - response.setCode(400); - response.setMsg("无效的施肥开关值: " + newValue); - } - } else if ("water_flow".equals(switchName)) { - try { - double flowRate = Double.parseDouble(newValue); - if (flowRate > 0 && flowRate <= 100) { - System.out.println("水流量设置为: " + flowRate + " L/min"); - response.setCode(200); - response.setMsg("水流量设置成功"); - } else { - response.setCode(400); - response.setMsg("水流量值超出范围 (0-100 L/min)"); - } - } catch (NumberFormatException e) { - response.setCode(400); - response.setMsg("无效的水流量值: " + newValue); - } - } else { - response.setCode(404); - response.setMsg("不支持的设备开关: " + switchName); - } - - return response; + return httpClientUtils.doPost(url, headers, requestBody, UpdateDeviceStatusRespVO.class); } private UpdateDeviceResponse convertToUnifiedUpdateResponse(UpdateDeviceStatusRespVO vendorResponse) { diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/HttpClientUtils.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/HttpClientUtils.java deleted file mode 100644 index 7366bc5e..00000000 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/HttpClientUtils.java +++ /dev/null @@ -1,215 +0,0 @@ -package cn.iocoder.yudao.module.farm.utils; - -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.springframework.stereotype.Component; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.time.Duration; -import java.util.List; -import java.util.Map; - -/** - * @description: http client - * @author: binda - * @date: 2025/9/16 16:46 - */ -@Component -public class HttpClientUtils { - private final HttpClient httpClient; - private final ObjectMapper objectMapper; - - public HttpClientUtils(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - this.httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build(); - } - - private String getBaseUrl(String hosts) { - if (hosts.startsWith("http")) { - return hosts; - } - return "https://" + hosts; - } - - // 通用GET请求 - 返回原始JsonNode,让调用方自己解析 - public JsonNode getRequestRaw(String hosts, - String path, - Map params, - Map headers) throws Exception { - - String queryString = buildQueryString(params); - HttpRequest request = buildRequest(hosts, path + queryString, "GET", null, headers); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - - if (response.statusCode() == 200) { - return objectMapper.readTree(response.body()); - } else { - throw new RuntimeException("HTTP request failed with status: " + response.statusCode()); - } - - } - - // 通用GET请求 - 自动解析为指定类型 - public ApiResponse getRequest(String hosts, - String path, - Map params, - Map headers, - Class dataType) throws Exception { - - JsonNode responseJson = getRequestRaw(hosts, path, params, headers); - return parseResponse(responseJson, dataType); - - } - - // 通用GET请求 - 自动解析为List类型 - public ApiResponse> getRequestAsList(String hosts, - String path, - Map params, - Map headers, - Class itemType) throws Exception { - - JsonNode responseJson = getRequestRaw(hosts, path, params, headers); - return parseResponseAsList(responseJson, itemType); - - } - - // 通用POST请求 - 返回原始JsonNode - public JsonNode postRequestRaw(String hosts, - String path, - Object requestBody, - Map headers) throws Exception { - - String requestBodyJson = objectMapper.writeValueAsString(requestBody); - - HttpRequest request = buildRequest(hosts, path, "POST", requestBodyJson, headers); - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - - if (response.statusCode() == 200) { - return objectMapper.readTree(response.body()); - } else { - throw new RuntimeException("HTTP request failed with status: " + response.statusCode()); - } - - } - - // 通用POST请求 - 自动解析为指定类型 - public ApiResponse postRequest(String hosts, - String path, - Object requestBody, - Map headers, - Class dataType) throws Exception { - - JsonNode responseJson = postRequestRaw(hosts, path, requestBody, headers); - return parseResponse(responseJson, dataType); - - } - - // 通用POST请求 - 自动解析为List类型 - public ApiResponse> postRequestAsList(String hosts, - String path, - Object requestBody, - Map headers, - Class itemType) throws Exception { - - JsonNode responseJson = postRequestRaw(hosts, path, requestBody, headers); - return parseResponseAsList(responseJson, itemType); - - } - - - // 构建查询字符串 - private String buildQueryString(Map params) throws UnsupportedEncodingException { - if (params == null || params.isEmpty()) { - return ""; - } - - StringBuilder queryBuilder = new StringBuilder("?"); - for (Map.Entry entry : params.entrySet()) { - if (queryBuilder.length() > 1) { - queryBuilder.append("&"); - } - queryBuilder.append(entry.getKey()) - .append("=") - .append(java.net.URLEncoder.encode(entry.getValue(), "UTF-8")); - } - return queryBuilder.toString(); - } - - // 构建HTTP请求 - private HttpRequest buildRequest(String hosts, - String path, - String method, - String requestBody, - Map headers) throws Exception { - - HttpRequest.Builder builder = HttpRequest.newBuilder() - .uri(URI.create(this.getBaseUrl(hosts) + "/" + path)) - .header("Content-Type", "application/json") - .timeout(Duration.ofSeconds(10)); - - if ("GET".equals(method)) { - builder.GET(); - } else if ("POST".equals(method)) { - builder.POST(HttpRequest.BodyPublishers.ofString(requestBody)); - } - - if (headers != null) { - for (Map.Entry entry : headers.entrySet()) { - builder.header(entry.getKey(), entry.getValue()); - } - } - - return builder.build(); - } - - // 解析响应为单个对象 - private ApiResponse parseResponse(JsonNode responseJson, Class dataType) { - String code = responseJson.get("code").asText(); - String message = responseJson.get("message").asText(); - JsonNode dataNode = responseJson.get("data"); - - T data = null; - if (dataNode != null && !dataNode.isNull()) { - data = objectMapper.convertValue(dataNode, dataType); - } - - return new ApiResponse<>(code, message, data); - } - - // 解析响应为List - private ApiResponse> parseResponseAsList(JsonNode responseJson, Class itemType) { - String code = responseJson.get("code").asText(); - String message = responseJson.get("message").asText(); - JsonNode dataNode = responseJson.get("data"); - - List data = null; - if (dataNode != null && !dataNode.isNull() && dataNode.isArray()) { - JavaType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, itemType); - data = objectMapper.convertValue(dataNode, listType); - } - - return new ApiResponse<>(code, message, data); - } - - @Data - @AllArgsConstructor - @NoArgsConstructor - public static class ApiResponse { - private String code; - private String message; - private T data; - - public boolean isSuccess() { - return "1000".equals(code); - } - } - -}