金山云服务API调用并入库,交换机管理功能新增
This commit is contained in:
+259
@@ -0,0 +1,259 @@
|
||||
package com.ruoyi.system.config;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.ruoyi.common.core.utils.DateUtils;
|
||||
import com.ruoyi.system.domain.EpsInitialTrafficData;
|
||||
import com.ruoyi.system.domain.RmRegistrationMachine;
|
||||
import com.ruoyi.system.service.EpsInitialTrafficDataService;
|
||||
import com.ruoyi.system.service.IRmRegistrationMachineService;
|
||||
import com.ruoyi.system.util.TableRouterUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URI;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class HmacScheduledTask {
|
||||
|
||||
private static final String MAC_NAME = "HmacSHA1";
|
||||
private static final String ENCODING = "UTF-8";
|
||||
|
||||
@Autowired
|
||||
private IRmRegistrationMachineService rmRegistrationMachineService;
|
||||
@Autowired
|
||||
private EpsInitialTrafficDataService epsInitialTrafficDataService;
|
||||
|
||||
|
||||
/**
|
||||
* 每小时执行一次,查询4小时前的数据
|
||||
* 例如:9:39执行时查询4:00-5:00的数据
|
||||
*/
|
||||
@Scheduled(cron = "0 0 * * * ?") // 每小时整点执行
|
||||
// 或者每5分钟执行一次:@Scheduled(cron = "0 */5 * * * ?")
|
||||
// @Scheduled(initialDelay = 5000, fixedDelay = Long.MAX_VALUE)
|
||||
public void executeHourlyTask() {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
try {
|
||||
System.out.println("开始执行定时任务,时间:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
|
||||
// 计算时间范围:当前时间往前推4小时的整点时间段
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
// 计算查询的时间段(4小时前的整点小时)
|
||||
LocalDateTime queryBaseTime = now.minusHours(4);
|
||||
LocalDateTime startTime = queryBaseTime.withMinute(0).withSecond(0).withNano(0);
|
||||
LocalDateTime endTime = startTime.plusHours(1);
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
String startTimeStr = startTime.format(formatter);
|
||||
String endTimeStr = endTime.format(formatter);
|
||||
|
||||
System.out.println("查询时间范围:" + startTimeStr + " 至 " + endTimeStr);
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String plainText = "efea5f0218c84a24b9fdab3264de3da5" + timestamp + "/supplier/outer/dev/getFlow";
|
||||
String secretKey = getHmac(plainText, "91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8");
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Content-Type", "application/json");
|
||||
headers.set("TOKEN", "efea5f0218c84a24b9fdab3264de3da5");
|
||||
headers.set("secret-key", secretKey);
|
||||
headers.set("timestamps", String.valueOf(timestamp));
|
||||
// 查询绑定的machinecode
|
||||
List<RmRegistrationMachine> machineList = rmRegistrationMachineService.selectRmRegistrationMachineList(new RmRegistrationMachine());
|
||||
for (RmRegistrationMachine rmRegistrationMachine : machineList) {
|
||||
// 构建URL
|
||||
URI uri = UriComponentsBuilder
|
||||
.fromHttpUrl("https://ecscm-openapi.ksyun.com/supplier/outer/dev/getFlow")
|
||||
.queryParam("srmChannel", "1000121954")
|
||||
.queryParam("startTime", startTimeStr)
|
||||
.queryParam("endTime", endTimeStr)
|
||||
.queryParam("machineCode", rmRegistrationMachine.getMachineCode())
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||
|
||||
// GET 请求
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
uri,
|
||||
HttpMethod.GET,
|
||||
entity,
|
||||
String.class
|
||||
);
|
||||
String result = response.getBody();
|
||||
// 保存流量数据
|
||||
parseAndProcessResponse(result, rmRegistrationMachine.getClientId());
|
||||
}
|
||||
System.out.println("定时任务执行完成");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("定时任务执行失败:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 解析和处理API响应
|
||||
*/
|
||||
private void parseAndProcessResponse(String responseBody, String clientId) {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
try {
|
||||
Map<String, Object> responseMap = objectMapper.readValue(responseBody, Map.class);
|
||||
|
||||
if (responseMap.get("code").equals(200)) {
|
||||
Map<String, Object> dataMap = (Map<String, Object>) responseMap.get("data");
|
||||
Integer total = (Integer) dataMap.get("total");
|
||||
List<Map<String, Object>> dataList = (List<Map<String, Object>>) dataMap.get("data");
|
||||
|
||||
System.out.println("成功获取数据,总记录数:" + total);
|
||||
|
||||
// 处理每条数据
|
||||
for (Map<String, Object> item : dataList) {
|
||||
processFlowData(item, clientId);
|
||||
}
|
||||
|
||||
} else {
|
||||
System.out.println("API返回错误:" + responseMap.get("msg"));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("JSON解析失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单条流量数据
|
||||
*/
|
||||
private void processFlowData(Map<String, Object> flowData, String clientId) {
|
||||
String time = (String) flowData.get("time");
|
||||
// 科学计数法转换为BigDecimal
|
||||
BigDecimal flow = Optional.ofNullable(flowData.get("flow"))
|
||||
.map(Object::toString)
|
||||
.map(str -> {
|
||||
try {
|
||||
return new BigDecimal(str);
|
||||
} catch (NumberFormatException e) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
})
|
||||
.orElse(BigDecimal.ZERO);
|
||||
// 字节转bit
|
||||
flow = flow.multiply(new BigDecimal(8));
|
||||
String flowPlain = flow.toPlainString();
|
||||
String deviceid = (String) flowData.get("deviceid");
|
||||
String ip = (String) flowData.get("ip");
|
||||
String province = (String) flowData.get("province");
|
||||
|
||||
System.out.println(String.format("时间:%s, 流量:%.2f, 设备:%s, IP:%s, 省份:%s",
|
||||
time, flow, deviceid, ip, province));
|
||||
|
||||
String tableName = TableRouterUtil.getTableName(TableRouterUtil.parseDateTime(time));
|
||||
EpsInitialTrafficData epsInitialTrafficData = new EpsInitialTrafficData();
|
||||
epsInitialTrafficData.setTableName(tableName);
|
||||
epsInitialTrafficData.setCreateTime(DateUtils.parseDate(time));
|
||||
epsInitialTrafficData.setClientId(clientId);
|
||||
epsInitialTrafficData.setMachineFlow(flowPlain);
|
||||
epsInitialTrafficDataService.updateMachineTraffic(epsInitialTrafficData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试方法:手动执行查询指定时间段
|
||||
*/
|
||||
public void manualExecuteForTimeRange(LocalDateTime start, LocalDateTime end) {
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
try {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
String startTimeStr = start.format(formatter);
|
||||
String endTimeStr = end.format(formatter);
|
||||
|
||||
System.out.println("手动执行查询,时间范围:" + startTimeStr + " 至 " + endTimeStr);
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String plainText = "efea5f0218c84a24b9fdab3264de3da5" + timestamp + "/supplier/outer/dev/getFlow";
|
||||
String secretKey = getHmac(plainText, "91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8");
|
||||
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Content-Type", "application/json");
|
||||
headers.set("TOKEN", "efea5f0218c84a24b9fdab3264de3da5");
|
||||
headers.set("secret-key", secretKey);
|
||||
headers.set("timestamps", String.valueOf(timestamp));
|
||||
|
||||
// 构建URL
|
||||
URI uri = UriComponentsBuilder
|
||||
.fromHttpUrl("https://ecscm-openapi.ksyun.com/supplier/outer/dev/getFlow")
|
||||
.queryParam("srmChannel", "1000121954")
|
||||
.queryParam("startTime", startTimeStr)
|
||||
.queryParam("endTime", endTimeStr)
|
||||
.build()
|
||||
.toUri();
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||
|
||||
// GET 请求
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
uri,
|
||||
HttpMethod.GET,
|
||||
entity,
|
||||
String.class
|
||||
);
|
||||
|
||||
System.out.println("手动执行API响应结果:" + response.getBody());
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("手动执行失败:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HMAC加密方法
|
||||
*/
|
||||
public static String getHmac(String plainText, String encryptKey) {
|
||||
try{
|
||||
byte[] dataKey = encryptKey.getBytes(ENCODING);
|
||||
byte[] dataValue = plainText.getBytes(ENCODING);
|
||||
SecretKey secretKey = new SecretKeySpec(dataKey, MAC_NAME);
|
||||
Mac mac = Mac.getInstance(MAC_NAME);
|
||||
mac.init(secretKey);
|
||||
byte[] bytes = mac.doFinal(dataValue);
|
||||
String rs = encodeHex(bytes, false);
|
||||
return rs;
|
||||
} catch (Exception e){
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据转16进制编码
|
||||
*/
|
||||
public static String encodeHex(final byte[] data, final boolean toLowerCase) {
|
||||
final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
final char[] toDigits = toLowerCase ? DIGITS_LOWER : DIGITS_UPPER;
|
||||
final int l = data.length;
|
||||
final char[] out = new char[l << 1];
|
||||
for (int i = 0, j = 0; i < l; i++) {
|
||||
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
|
||||
out[j++] = toDigits[0x0F & data[i]];
|
||||
}
|
||||
return new String(out);
|
||||
}
|
||||
}
|
||||
+20
@@ -72,6 +72,26 @@ public class TableScheduleConfig {
|
||||
.thenRun(() -> executeWithLog("交换机带宽1024",
|
||||
() -> initialSwitchInfoDetailsService.calculateSwitch95BandwidthDaily(initialSwitchInfoDetails, dailyStartTime, dailyEndTime, "1024")));
|
||||
}
|
||||
// 每天5点04执行 计算金山95带宽值/日
|
||||
@Scheduled(cron = "0 4 5 * * ?", zone = "Asia/Shanghai")
|
||||
public void calculateJinShan95() {
|
||||
// 获取昨天的日期范围(北京时间)
|
||||
LocalDate yesterday = LocalDate.now(ZoneId.of("Asia/Shanghai")).minusDays(1);
|
||||
String dailyStartTime = yesterday.atStartOfDay().format(TIME_FORMAT); // 00:00:00
|
||||
String dailyEndTime = yesterday.atTime(23, 59, 59).format(TIME_FORMAT); // 23:59:59
|
||||
// 日
|
||||
String dayOrMonth = "1";
|
||||
// 95带宽值/日
|
||||
EpsInitialTrafficData queryParam = new EpsInitialTrafficData();
|
||||
queryParam.setDayOrMonth(dayOrMonth);
|
||||
InitialSwitchInfoDetails initialSwitchInfoDetails = new InitialSwitchInfoDetails();
|
||||
initialSwitchInfoDetails.setDayOrMonth(dayOrMonth);
|
||||
// 顺序执行链
|
||||
CompletableFuture.runAsync(() -> executeWithLog("金山业务带宽1000",
|
||||
() -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1000")))
|
||||
.thenRun(() -> executeWithLog("金山业务带宽1024",
|
||||
() -> epsInitialTrafficDataService.calculate95ByJinShan(queryParam, dailyStartTime, dailyEndTime, "1024")));
|
||||
}
|
||||
|
||||
// 每月1号0点执行 计算95带宽值/月
|
||||
@Scheduled(cron = "0 3 0 1 * ?", zone = "Asia/Shanghai")
|
||||
|
||||
Reference in New Issue
Block a user