This commit is contained in:
parent
cd9227be31
commit
5274fb8d64
@ -1,21 +1,21 @@
|
||||
package org.dromara.sis.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* 应用配置类
|
||||
*/
|
||||
@Configuration
|
||||
public class SOSAppConfig {
|
||||
|
||||
/**
|
||||
* 配置 RestTemplate 用于 API 调用
|
||||
* @return RestTemplate 实例
|
||||
*/
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
||||
//package org.dromara.sis.config;
|
||||
//
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.web.client.RestTemplate;
|
||||
//
|
||||
///**
|
||||
// * 应用配置类
|
||||
// */
|
||||
//@Configuration
|
||||
//public class SOSAppConfig {
|
||||
//
|
||||
// /**
|
||||
// * 配置 RestTemplate 用于 API 调用
|
||||
// * @return RestTemplate 实例
|
||||
// */
|
||||
// @Bean
|
||||
// public RestTemplate restTemplate() {
|
||||
// return new RestTemplate();
|
||||
// }
|
||||
//}
|
||||
|
@ -4,16 +4,17 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.sis.service.ApiService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* API 服务实现类
|
||||
* 负责与外部 API 进行通信
|
||||
* API服务实现类,支持获取Token、刷新Token和401响应处理
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
@ -22,34 +23,43 @@ public class ApiServiceImpl implements ApiService {
|
||||
@Value("${api.url}")
|
||||
private String apiUrl;
|
||||
|
||||
@Value("${api.authUrl}")
|
||||
private String authUrl; // 认证URL: /sos/v1/mntn/account/appId/token
|
||||
|
||||
@Value("${api.refreshUrl}")
|
||||
private String refreshUrl; // 刷新Token URL: /sos/v1/mntn/account/refresh/token
|
||||
|
||||
@Value("${api.appId}")
|
||||
private String appId;
|
||||
|
||||
@Value("${api.appCode}")
|
||||
private String appCode;
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
// 缓存Token信息
|
||||
private static final Map<String, TokenInfo> tokenCache = new ConcurrentHashMap<>();
|
||||
|
||||
public ApiServiceImpl(RestTemplate restTemplate) {
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Retryable(value = {HttpClientErrorException.Unauthorized.class}, maxAttempts = 2, backoff = @Backoff(delay = 1000))
|
||||
public Map<String, Object> fetchAlarmRecords(int pageNum, int pageSize) {
|
||||
String token = getAccessToken();
|
||||
|
||||
// 设置请求头,添加Token
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.set("token", token); // 根据接口要求,使用"Token"而非"Authorization"
|
||||
|
||||
// 构建请求体
|
||||
Map<String, Object> requestBody = buildRequestParams(pageNum, pageSize);
|
||||
|
||||
log.info("请求参数:{}", requestBody);
|
||||
try {
|
||||
// 设置请求头
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
// 构建请求体
|
||||
Map<String, Object> requestBody = new HashMap<>();
|
||||
requestBody.put("PageSize", pageSize);
|
||||
requestBody.put("PageNum", pageNum);
|
||||
|
||||
List<List<Map<String, Object>>> filters = List.of(
|
||||
List.of(Map.of("Key", "FinishTime", "Type", "str", "Value", "2025-07-27"))
|
||||
);
|
||||
requestBody.put("Filters", filters);
|
||||
|
||||
requestBody.put("OrderKey", "StartTime");
|
||||
requestBody.put("Desc", "0");
|
||||
requestBody.put("OrFirst", true);
|
||||
|
||||
// 发送请求
|
||||
// 发送带Token的请求
|
||||
HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);
|
||||
ResponseEntity<Map> response = restTemplate.exchange(
|
||||
apiUrl,
|
||||
@ -57,23 +67,225 @@ public class ApiServiceImpl implements ApiService {
|
||||
requestEntity,
|
||||
Map.class
|
||||
);
|
||||
log.info("请求返回:{}", response);
|
||||
|
||||
// 处理响应
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
Map<String, Object> result = response.getBody();
|
||||
if (result != null && result.get("Status").equals(0)) {
|
||||
return result;
|
||||
} else {
|
||||
log.error("API 返回错误状态: {}", result);
|
||||
log.error("API返回错误状态: {}", result);
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
log.error("API 请求失败,状态码: {}", response.getStatusCode());
|
||||
log.error("API请求失败,状态码: {}", response.getStatusCode());
|
||||
return null;
|
||||
}
|
||||
} catch (HttpClientErrorException.Unauthorized e) {
|
||||
// 捕获401错误,清除缓存的Token并重试
|
||||
log.warn("Token已过期,清除缓存并尝试重新获取: {}", e.getMessage());
|
||||
tokenCache.remove(appId);
|
||||
// 重新获取Token并再次调用(由@Retryable注解处理)
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("调用 API 异常: {}", e.getMessage(), e);
|
||||
log.error("调用API异常: {}", e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取访问Token
|
||||
*/
|
||||
private synchronized String getAccessToken() {
|
||||
// 检查缓存中是否有有效的Token
|
||||
TokenInfo tokenInfo = tokenCache.get(appId);
|
||||
if (tokenInfo != null && !isTokenExpired(tokenInfo)) {
|
||||
return tokenInfo.getAccessToken();
|
||||
}
|
||||
|
||||
// 尝试刷新Token
|
||||
if (tokenInfo != null && tokenInfo.getRefreshToken() != null) {
|
||||
log.info("尝试刷新现有Token...");
|
||||
try {
|
||||
String refreshedToken = refreshAccessToken(tokenInfo.getRefreshToken());
|
||||
if (refreshedToken != null) {
|
||||
return refreshedToken;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("刷新Token失败,将重新获取: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存中没有有效Token或刷新失败,重新获取
|
||||
log.info("正在获取新的访问Token...");
|
||||
try {
|
||||
// 构建获取Token的请求体
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("AppId", appId);
|
||||
body.put("AppCode", appCode);
|
||||
|
||||
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
|
||||
|
||||
// 发送获取Token的请求
|
||||
ResponseEntity<Map> response = restTemplate.postForEntity(
|
||||
authUrl,
|
||||
request,
|
||||
Map.class
|
||||
);
|
||||
log.info("接口响应:{},状态码:{}",response,response.getStatusCode());
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
Map<String, Object> tokenResponse = response.getBody();
|
||||
if (tokenResponse != null && tokenResponse.get("Status").equals(0)) {
|
||||
String accessToken = (String) tokenResponse.get("Token");
|
||||
String refreshToken = (String) tokenResponse.get("RefreshToken");
|
||||
Integer expireIn = (Integer) tokenResponse.get("ExpireIn");
|
||||
|
||||
// 缓存新获取的Token,设置过期时间(提前1分钟,避免临界点问题)
|
||||
TokenInfo newTokenInfo = new TokenInfo(
|
||||
accessToken,
|
||||
refreshToken,
|
||||
System.currentTimeMillis() + (expireIn - 60) * 1000
|
||||
);
|
||||
tokenCache.put(appId, newTokenInfo);
|
||||
|
||||
log.info("成功获取新的访问Token,有效期: {}秒", expireIn);
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
|
||||
log.error("获取Token失败,状态码: {}", response.getStatusCode());
|
||||
throw new RuntimeException("获取访问Token失败");
|
||||
} catch (Exception e) {
|
||||
log.error("获取Token异常: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("获取访问Token异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新访问Token
|
||||
*/
|
||||
private String refreshAccessToken(String refreshToken) {
|
||||
try {
|
||||
// 构建刷新Token的请求体
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
Map<String, Object> body = new HashMap<>();
|
||||
body.put("RefreshToken", refreshToken);
|
||||
|
||||
HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
|
||||
|
||||
// 发送刷新Token的请求
|
||||
ResponseEntity<Map> response = restTemplate.postForEntity(
|
||||
refreshUrl,
|
||||
request,
|
||||
Map.class
|
||||
);
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
Map<String, Object> tokenResponse = response.getBody();
|
||||
if (tokenResponse != null && tokenResponse.get("Status").equals(0)) {
|
||||
String accessToken = (String) tokenResponse.get("Token");
|
||||
String newRefreshToken = (String) tokenResponse.get("RefreshToken");
|
||||
Integer expireIn = (Integer) tokenResponse.get("ExpireIn");
|
||||
|
||||
// 更新缓存的Token信息
|
||||
TokenInfo tokenInfo = tokenCache.get(appId);
|
||||
if (tokenInfo != null) {
|
||||
tokenInfo.setAccessToken(accessToken);
|
||||
tokenInfo.setRefreshToken(newRefreshToken);
|
||||
tokenInfo.setExpireTime(System.currentTimeMillis() + (expireIn - 60) * 1000);
|
||||
}
|
||||
|
||||
log.info("成功刷新访问Token,有效期: {}秒", expireIn);
|
||||
return accessToken;
|
||||
}
|
||||
}
|
||||
|
||||
log.warn("刷新Token失败,将重新获取");
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.warn("刷新Token异常: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Token是否已过期
|
||||
*/
|
||||
private boolean isTokenExpired(TokenInfo tokenInfo) {
|
||||
return tokenInfo.getExpireTime() < System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建请求参数
|
||||
*/
|
||||
private Map<String, Object> buildRequestParams(int pageNum, int pageSize) {
|
||||
Map<String, Object> requestBody = new HashMap<>();
|
||||
requestBody.put("PageSize", pageSize);
|
||||
requestBody.put("PageNum", pageNum);
|
||||
requestBody.put("OrFirst", true);
|
||||
requestBody.put("Filters", Collections.emptyList()); // 空过滤器
|
||||
requestBody.put("OrderKey", "StartTime");
|
||||
requestBody.put("Desc", 1); // 降序排列
|
||||
|
||||
return requestBody;
|
||||
}
|
||||
// private Map<String, Object> buildRequestParams(int pageNum, int pageSize) {
|
||||
// Map<String, Object> requestBody = new HashMap<>();
|
||||
// requestBody.put("'PageSize'", pageSize);
|
||||
// requestBody.put("'PageNum'", pageNum);
|
||||
//
|
||||
// List<List<Map<String, Object>>> filters = new ArrayList<>();
|
||||
// requestBody.put("'Filters'", filters);
|
||||
//
|
||||
// requestBody.put("'OrderKey'", "'StartTime'");
|
||||
// requestBody.put("'Desc'", "1");
|
||||
// requestBody.put("'OrFirst'", true);
|
||||
//
|
||||
// return requestBody;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Token信息内部类(修改为可更新的类)
|
||||
*/
|
||||
private static class TokenInfo {
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
private long expireTime;
|
||||
|
||||
public TokenInfo(String accessToken, String refreshToken, long expireTime) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public long getExpireTime() {
|
||||
return expireTime;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public void setExpireTime(long expireTime) {
|
||||
this.expireTime = expireTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class DataSyncTask {
|
||||
// 提取操作记录数据
|
||||
Map<Long, List<Map<String, Object>>> operatorMap = new HashMap<>();
|
||||
for (Map<String, Object> recordMap : recordList) {
|
||||
Long recordId = (Long) recordMap.get("Id");
|
||||
Long recordId = Long.valueOf((Integer)recordMap.get("Id"));
|
||||
List<Map<String, Object>> operators = (List<Map<String, Object>>) recordMap.get("TaskOperators");
|
||||
if (operators != null && !operators.isEmpty()) {
|
||||
operatorMap.put(recordId, operators);
|
||||
|
@ -13,7 +13,10 @@ spring:
|
||||
# API 配置
|
||||
api:
|
||||
url: https://norsos.lionking110.com/sos/v1/mntn/business/appId/alarm/list
|
||||
|
||||
authUrl: https://norsos.lionking110.com/sos/v1/mntn/account/appId/token
|
||||
refreshUrl: https://norsos.lionking110.com/sos/v1/mntn/account/refresh/token
|
||||
appId: dfc7ec7507de4626b8c920c4fe1ff8b1
|
||||
appCode: fe11d05aa5704dffaa0b1c4b56ba80b2
|
||||
# 同步配置
|
||||
sync:
|
||||
pageSize: 100
|
||||
|
@ -40,9 +40,9 @@ spring.sql.init.platform=mysql
|
||||
db.num=1
|
||||
|
||||
### Connect URL of DB:
|
||||
db.url.0=jdbc:mysql://127.0.0.1:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
|
||||
db.url.0=jdbc:mysql://47.109.37.87:23306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
|
||||
db.user.0=root
|
||||
db.password.0=root
|
||||
db.password.0=admin@123456
|
||||
|
||||
### the maximum retry times for push
|
||||
nacos.config.push.maxRetryTime=50
|
||||
|
Loading…
Reference in New Issue
Block a user