我把全链路发给你:发送端:package com.ceprei.rcm.util;
import com.alibaba.fastjson.JSONObject;
import jnpf.util.wxutil.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.PointData;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* HC-DB数据库接口访问工具类(带重载方法)
*/
public class HcdbApiUtil {
private static final Logger log = LoggerFactory.getLogger(HcdbApiUtil.class);
// HC-DB服务器地址配置
// private static final String HCDB_BASE_URL = "http://10.21.8.190:8001";
private static final String HCDB_BASE_URL = "http://127.0.0.1:8001";
// 接口路径
private static final String LATEST_DATA_URL = HCDB_BASE_URL + "/hcdb/data/consume/latest";
private static final String HISTORY_DATA_URL = HCDB_BASE_URL + "/hcdb/data/consume";
// 默认参数值
private static final Integer DEFAULT_RETURN_POINT_LIST = 0; // 默认不返回测点编码列表
private static final Integer DEFAULT_INTERVAL = 1; // 默认采样间隔1秒
private HcdbApiUtil() {
throw new IllegalAccessError("工具类不能实例化");
}
// ==================== 实时数据查询方法重载 ====================
/**
* 获取实时数据(最简版本,只传测点编码列表)
* @param pointList 测点编码列表
* @return 响应结果
*/
public static JSONObject getLatestData(List<String> pointList) {
return getLatestData(pointList, DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取实时数据(完整参数)
* @param pointList 测点编码列表
* @param returnPointList 是否返回测点编码列表 (1:返回, 其他:不返回)
* @return 响应结果
* 返回值格式:{
* "msg": "success",
* "code": 200,
* "content": {
* "dataList": [1.5, 2.5],
* "pointList": ["W3.UNIT1.GROSS_MW", "W3.UNIT2.GROSS_MW"]
* }
* }
*/
public static JSONObject getLatestData(List<String> pointList, Integer returnPointList) {
try {
// 构建请求体
JSONObject requestBody = new JSONObject();
requestBody.put("pointList", pointList);
if (returnPointList != null) {
requestBody.put("returnPointList", returnPointList);
}
// 发送POST请求
String response = HttpUtil.sendHttpPost(LATEST_DATA_URL, requestBody.toJSONString());
if (response == null || response.trim().isEmpty()) {
log.error("获取实时数据失败: 响应为空");
return createErrorResponse(500, "响应为空");
}
return JSONObject.parseObject(response);
} catch (Exception e) {
log.error("获取实时数据异常", e);
return createErrorResponse(500, "请求异常: " + e.getMessage());
}
}
/**
* 获取实时数据(字符串数组版本)
* @param points 测点数组
* @return 响应结果
*/
public static JSONObject getLatestData(String... points) {
return getLatestData(Arrays.asList(points), DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取实时数据(字符串数组版本,带返回测点编码列表选项)
* @param returnPointList 是否返回测点编码列表
* @param points 测点数组
* @return 响应结果
*/
public static JSONObject getLatestData(Integer returnPointList, String... points) {
return getLatestData(Arrays.asList(points), returnPointList);
}
// ==================== 历史数据查询方法重载 ====================
/**
* 获取历史数据(最简版本,只传测点编码列表和起止时间)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @return 响应结果
*/
public static JSONObject getHistoryData(List<String> pointList, String startTime, String stopTime) {
return getHistoryData(pointList, startTime, stopTime, DEFAULT_INTERVAL, DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取历史数据(带间隔参数)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔(秒)
* @return 响应结果
*/
public static JSONObject getHistoryData(List<String> pointList, String startTime,
String stopTime, Integer interval) {
return getHistoryData(pointList, startTime, stopTime, interval, DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取历史数据(完整参数)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔(秒)
* @param returnPointList 是否返回测点编码列表 (1:返回, 其他:不返回)
* @return 响应结果
*/
public static JSONObject getHistoryData(List<String> pointList, String startTime,
String stopTime, Integer interval, Integer returnPointList) {
try {
// 构建请求体
JSONObject requestBody = new JSONObject();
requestBody.put("pointList", pointList);
requestBody.put("startTime", startTime);
requestBody.put("stopTime", stopTime);
requestBody.put("interval", interval);
if (returnPointList != null) {
requestBody.put("returnPointList", returnPointList);
}
// 发送POST请求
String response = HttpUtil.sendHttpPost(HISTORY_DATA_URL, requestBody.toJSONString());
if (response == null || response.trim().isEmpty()) {
log.error("获取历史数据失败: 响应为空");
return createErrorResponse(500, "响应为空");
}
return JSONObject.parseObject(response);
} catch (Exception e) {
log.error("获取历史数据异常", e);
return createErrorResponse(500, "请求异常: " + e.getMessage());
}
}
/**
* 获取历史数据(字符串数组版本,只传测点编码列表和起止时间)
* @param startTime 开始时间
* @param stopTime 结束时间
* @param points 测点数组
* @return 响应结果
*/
public static JSONObject getHistoryData(String startTime, String stopTime, String... points) {
return getHistoryData(Arrays.asList(points), startTime, stopTime, DEFAULT_INTERVAL, DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取历史数据(字符串数组版本,带间隔参数)
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔(秒)
* @param points 测点数组
* @return 响应结果
*/
public static JSONObject getHistoryData(String startTime, String stopTime, Integer interval, String... points) {
return getHistoryData(Arrays.asList(points), startTime, stopTime, interval, DEFAULT_RETURN_POINT_LIST);
}
// ==================== 简化数据获取方法重载 ====================
/**
* 获取实时数据(单测点简化版,只传单测点编码)
* @param pointKey 测点编码
* @return 单测点数值
*/
public static PointData getLatestDataSimple(String pointKey) {
List<Double> latestDataSimple = getLatestDataSimple(Collections.singletonList(pointKey), DEFAULT_RETURN_POINT_LIST);
if (latestDataSimple.isEmpty()){
return null;
}else{
PointData pointData = new PointData();
pointData.setTs(new Timestamp(new Date().getTime()));
pointData.setCurrent(latestDataSimple.get(0));
return pointData;
}
}
/**
* 获取实时数据(返回结构:Map<测点编码, PointData>)
* @param pointList 测点编码列表
* @return Map<String, PointData> 测点编码 -> 最新数据对象(自动填充当前时间)
*/
public static Map<String, PointData> getLatestDataMap(List<String> pointList) {
Map<String, PointData> result = new LinkedHashMap<>(); // 保持插入顺序
if (pointList == null || pointList.isEmpty()) return result;
// 获取原始数据(强制返回测点编码列表)
JSONObject response = getLatestData(pointList, DEFAULT_INTERVAL);
if (!isSuccess(response)) return result;
JSONObject content = response.getJSONObject("content");
if (content == null) return result;
// 解析数据(防御性处理)
List<Double> dataList = Optional.ofNullable(content.getJSONArray("datalist"))
.map(arr -> arr.toJavaList(Double.class))
.orElse(Collections.emptyList());
List<String> respPointList = Optional.ofNullable(content.getJSONArray("pointList"))
.map(arr -> arr.toJavaList(String.class))
.orElse(pointList); // 若未返回测点列表,使用输入列表
// 构建结果(自动填充当前时间)
Timestamp now = new Timestamp(System.currentTimeMillis());
IntStream.range(0, Math.min(respPointList.size(), dataList.size()))
.forEach(i -> {
String point = respPointList.get(i);
Double value = dataList.get(i);
result.put(point, new PointData(now, value));
});
return result;
}
/**
* 获取实时数据(简化版,只传测点编码列表)
* @param pointList 测点编码列表
* @return 数据列表
*/
public static List<Double> getLatestDataSimple(List<String> pointList) {
return getLatestDataSimple(pointList, DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取实时数据(简化版,完整参数)
* @param pointList 测点编码列表
* @param returnPointList 是否返回测点编码列表
* @return 数据列表
*/
public static List<Double> getLatestDataSimple(List<String> pointList, Integer returnPointList) {
JSONObject response = getLatestData(pointList, returnPointList);
if (isSuccess(response)) {
JSONObject content = response.getJSONObject("content");
if (content != null && content.containsKey("datalist")) {
return content.getJSONArray("datalist").toJavaList(Double.class);
}
}
return Collections.emptyList();
}
/**
* 获取实时数据(简化版,字符串数组版本)
* @param points 测点数组
* @return 数据列表
*/
public static List<Double> getLatestDataSimple(String... points) {
return getLatestDataSimple(Arrays.asList(points), DEFAULT_RETURN_POINT_LIST);
}
/**
* 获取历史数据(单测点简化版,只传测点编码列表和起止时间)
* @param point 测点编码
* @param startTime 开始时间
* @param stopTime 结束时间
* @return 单个测点列表
*/
public static List<PointData> getHistoryDataSimple(String point, String startTime, String stopTime) {
// 将单个测点转为List传给原方法
Map<String, Object> historyDataSimple = getHistoryDataSimple(
Collections.singletonList(point), startTime, stopTime, DEFAULT_INTERVAL, 1
);
List<PointData> result = new ArrayList<>();
if (!historyDataSimple.isEmpty()) {
List<String> timeList = (List<String>) historyDataSimple.get("timeList");
List<List<Double>> dataList = (List<List<Double>>) historyDataSimple.get("datalist");
if (timeList != null && dataList != null && !dataList.isEmpty()) {
// 取dataList的第一个(也是唯一一个)子列表
List<Double> pointValues = dataList.get(0);
// 遍历时间序列
for (int i = 0; i < timeList.size(); i++) {
Timestamp timestamp = Timestamp.valueOf(timeList.get(i));
Double value = (i < pointValues.size()) ? pointValues.get(i) : null;
result.add(new PointData(timestamp, value));
}
}
}
return result;
}
/**
* 获取历史数据(返回结构:Map<测点编码, List<PointData>>)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @return Map<String, List<PointData>> 测点编码 -> 时间序列数据
*/
public static Map<String, List<PointData>> getHistoryDataSimpleMap(
List<String> pointList, String startTime, String stopTime) {
JSONObject response = getHistoryData(pointList, startTime, stopTime, DEFAULT_INTERVAL, 1);
Map<String, List<PointData>> result = new LinkedHashMap<>(); // 保持插入顺序
if (!isSuccess(response)) return result;
JSONObject content = response.getJSONObject("content");
if (content == null) return result;
// 一次性解析所有基础数据
List<String> timeList = safeGetStringList(content, "timeList");
List<List<Double>> dataList = safeGetDoubleList(content, "datalist");
List<String> respPointList = safeGetStringList(content, "pointList");
// 使用Stream并行处理测点数据(线程安全)
respPointList.stream().forEach(point -> {
int index = respPointList.indexOf(point);
List<PointData> pointData = (index < dataList.size())
? buildPointDataList(timeList, dataList.get(index))
: Collections.emptyList();
result.put(point, pointData);
});
return result;
}
// 类型安全的辅助方法
private static List<String> safeGetStringList(JSONObject obj, String key) {
return Optional.ofNullable(obj.getJSONArray(key))
.map(arr -> arr.toJavaList(String.class))
.orElse(Collections.emptyList());
}
private static List<List<Double>> safeGetDoubleList(JSONObject obj, String key) {
return Optional.ofNullable(obj.getJSONArray(key))
.map(arr -> arr.toJavaList(List.class))
.map(list -> list.stream()
.map(inner -> ((List<?>) inner).stream()
.map(e -> e instanceof Number ? ((Number) e).doubleValue() : null)
.collect(Collectors.toList()))
.collect(Collectors.toList()))
.orElse(Collections.emptyList());
}
private static List<PointData> buildPointDataList(List<String> timeList, List<Double> values) {
return IntStream.range(0, timeList.size())
.mapToObj(i -> {
try {
Timestamp ts = Timestamp.valueOf(timeList.get(i));
Double val = (i < values.size()) ? values.get(i) : null;
return new PointData(ts, val);
} catch (Exception e) {
return new PointData(null, null); // 错误处理
}
})
.collect(Collectors.toList());
}
/**
* 获取历史数据(简化版,只传测点编码列表和起止时间)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @return 包含时间列表和数据二维列表的Map
*/
public static Map<String, Object> getHistoryDataSimple(List<String> pointList, String startTime, String stopTime) {
return getHistoryDataSimple(pointList, startTime, stopTime, DEFAULT_INTERVAL, 1);
}
/**
* 获取历史数据(简化版,带间隔参数)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔
* @return 包含时间列表和数据二维列表的Map
*/
public static Map<String, Object> getHistoryDataSimple(List<String> pointList, String startTime,
String stopTime, Integer interval) {
return getHistoryDataSimple(pointList, startTime, stopTime, interval, 1);
}
/**
* 获取历史数据(简化版,完整参数)
* @param pointList 测点编码列表
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔
* @param returnPointList 是否返回测点编码列表
* @return 包含时间列表和数据二维列表的Map
* 接口返回格式:pointList个数与dataList中子列表个数一致,子列表个数与timeList个数一致
* {
* "msg": "success",
* "code": 200,
* "content": {
* "timeList": [
* "2021-01-01 00:00:00",
* "2021-01-01 00:00:02",
* "2021-01-01 00:00:04"
* ],
* "dataList": [
* [1.1, 1.3, 1.5],
* [2.1, 2.3, 2.5]
* ],
* "pointList": ["W3.UNIT1.GROSS_MW", "W3.UNIT2.GROSS_MW"]
* }
* }
*/
public static Map<String, Object> getHistoryDataSimple(List<String> pointList, String startTime,
String stopTime, Integer interval, Integer returnPointList) {
JSONObject response = getHistoryData(pointList, startTime, stopTime, interval, returnPointList);
Map<String, Object> result = new HashMap<>();
if (isSuccess(response)) {
JSONObject content = response.getJSONObject("content");
if (content != null) {
if (content.containsKey("timeList")) {
result.put("timeList", content.getJSONArray("timeList").toJavaList(String.class));
}
if (content.containsKey("datalist")) {
result.put("datalist", content.getJSONArray("datalist").toJavaList(List.class));
}
if (content.containsKey("pointList")) {
result.put("pointList", content.getJSONArray("pointList").toJavaList(String.class));
}
}
}
return result;
}
/**
* 获取历史数据(简化版,字符串数组版本)
* @param startTime 开始时间
* @param stopTime 结束时间
* @param points 测点数组
* @return 包含时间列表和数据二维列表的Map
*/
public static Map<String, Object> getHistoryDataSimple(String startTime, String stopTime, String... points) {
return getHistoryDataSimple(Arrays.asList(points), startTime, stopTime, DEFAULT_INTERVAL, 1);
}
/**
* 获取历史数据(简化版,字符串数组版本,带间隔参数)
* @param startTime 开始时间
* @param stopTime 结束时间
* @param interval 采样间隔
* @param points 测点数组
* @return 包含时间列表和数据二维列表的Map
*/
public static Map<String, Object> getHistoryDataSimple(String startTime, String stopTime,
Integer interval, String... points) {
return getHistoryDataSimple(Arrays.asList(points), startTime, stopTime, interval, 1);
}
// ==================== 辅助方法 ====================
/**
* 检查响应是否成功
* @param response 响应对象
* @return 是否成功
*/
public static boolean isSuccess(JSONObject response) {
return response != null && response.getIntValue("code") == 200;
}
/**
* 获取错误信息
* @param response 响应对象
* @return 错误信息
*/
public static String getErrorMessage(JSONObject response) {
if (response == null) {
return "响应为空";
}
return response.getString("msg");
}
/**
* 创建错误响应
* @param code 错误码
* @param message 错误信息
* @return 错误响应JSON
*/
private static JSONObject createErrorResponse(int code, String message) {
JSONObject errorResponse = new JSONObject();
errorResponse.put("code", code);
errorResponse.put("msg", message);
errorResponse.put("content", null);
return errorResponse;
}
/**
* 批量获取多个测点的实时数据
* @param pointCodes 测点编码列表
* @return 测点编码到值的映射
*/
public static Map<String, Double> batchGetLatestData(List<String> pointCodes) {
JSONObject response = getLatestData(pointCodes, 1);
Map<String, Double> result = new HashMap<>();
if (isSuccess(response)) {
JSONObject content = response.getJSONObject("content");
if (content != null && content.containsKey("datalist") && content.containsKey("pointList")) {
List<Double> dataList = content.getJSONArray("datalist").toJavaList(Double.class);
List<String> pointList = content.getJSONArray("pointList").toJavaList(String.class);
for (int i = 0; i < pointList.size(); i++) {
if (i < dataList.size()) {
result.put(pointList.get(i), dataList.get(i));
}
}
}
}
return result;
}
/**
* 批量获取多个测点的实时数据(字符串数组版本)
* @param points 测点数组
* @return 测点编码到值的映射
*/
public static Map<String, Double> batchGetLatestData(String... points) {
return batchGetLatestData(Arrays.asList(points));
}
}接收端:package com.ceprei.rcm.controller;
import com.ceprei.rcm.model.request.HistoryDataRequest;
import com.ceprei.rcm.model.request.LatestDataRequest;
import com.ceprei.rcm.model.response.ApiResponse;
import com.ceprei.rcm.model.response.HistoryDataResponse;
import com.ceprei.rcm.model.response.LatestDataResponse;
import com.ceprei.rcm.service.CsvDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/hcdb/data/consume")
public class DataController {
@Autowired
private CsvDataService csvDataService;
@PostMapping("/latest")
public ApiResponse<LatestDataResponse> getLatestData(@RequestBody LatestDataRequest request) {
try {
List<Double> dataList = new ArrayList<>();
List<String> pointList = request.getPointList();
if (pointList == null || pointList.isEmpty()) {
return ApiResponse.error("测点列表不能为空");
}
for (String point : pointList) {
Double value = csvDataService.getLatestValueAsDouble(point);
dataList.add(value);
}
LatestDataResponse content = new LatestDataResponse();
content.setDatalist(dataList);
if (request.getReturnPointList() != null && request.getReturnPointList() == 1) {
content.setPointList(pointList);
}
return ApiResponse.success(content);
} catch (Exception e) {
return ApiResponse.error("服务器错误: " + e.getMessage());
}
}
@PostMapping
public ApiResponse<HistoryDataResponse> getHistoryData(@RequestBody HistoryDataRequest request) {
try {
List<String> pointList = request.getPointList();
if (pointList == null || pointList.isEmpty()) {
return ApiResponse.error("测点列表不能为空");
}
if (request.getStartTime() == null || request.getStopTime() == null) {
return ApiResponse.error("开始时间和结束时间不能为空");
}
List<List<Double>> dataList = new ArrayList<>();
for (String point : pointList) {
List<Double> pointData = csvDataService.getDataInRangeAsDoubleList(
point, request.getStartTime(), request.getStopTime());
dataList.add(pointData);
}
// 生成时间列表
List<String> timeList = csvDataService.generateTimeList(
request.getStartTime(), request.getStopTime(), request.getInterval());
HistoryDataResponse content = new HistoryDataResponse();
content.setTimeList(timeList);
content.setDatalist(dataList);
if (request.getReturnPointList() != null && request.getReturnPointList() == 1) {
content.setPointList(pointList);
}
return ApiResponse.success(content);
} catch (Exception e) {
return ApiResponse.error("服务器错误: " + e.getMessage());
}
}
}