|
@@ -1,12 +1,13 @@
|
|
|
package org.jeecg.modules.adweb.dmp.controller;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.google.common.cache.Cache;
|
|
|
+import com.google.common.cache.CacheBuilder;
|
|
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
|
import org.apache.shiro.SecurityUtils;
|
|
|
import org.jeecg.common.api.vo.Result;
|
|
@@ -24,7 +25,8 @@ import org.springframework.web.client.RestClientResponseException;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
import java.util.Objects;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
+import java.util.concurrent.ExecutionException;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
@@ -52,24 +54,25 @@ public class TradeSparqController {
|
|
|
|
|
|
@Autowired private AdwebRedisUtil adwebRedisUtil;
|
|
|
|
|
|
- private RestTemplate restTemplate = new RestTemplate();
|
|
|
+ @Autowired private RestTemplate restTemplate;
|
|
|
|
|
|
- // 用户级加锁,确保TradeSparq API串行调用,准确控制额度
|
|
|
- private final ConcurrentHashMap<String, Object> userLocks = new ConcurrentHashMap<>();
|
|
|
+ // 用户级加锁,确保TradeSparq API串行调用,准确控制用户额度
|
|
|
+ private final Cache<String, Object> userLocks =
|
|
|
+ CacheBuilder.newBuilder().expireAfterAccess(1, TimeUnit.HOURS).build();
|
|
|
|
|
|
@PostMapping("/**")
|
|
|
@ResponseBody
|
|
|
public Result<JSONObject> forwardPost(
|
|
|
- HttpServletRequest httpRequest, @RequestBody JSONObject requestBody) {
|
|
|
- String uid = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getId();
|
|
|
- if (StringUtils.isBlank(uid)) {
|
|
|
- return Result.error("用户ID为空");
|
|
|
+ HttpServletRequest httpRequest, @RequestBody JSONObject requestBody)
|
|
|
+ throws ExecutionException {
|
|
|
+ LoginUser loginUser = ((LoginUser) SecurityUtils.getSubject().getPrincipal());
|
|
|
+ if (Objects.isNull(loginUser)) {
|
|
|
+ return Result.error("用户信息未找到");
|
|
|
}
|
|
|
|
|
|
// 获取用户锁
|
|
|
- Object userLock = userLocks.computeIfAbsent(uid, k -> new Object());
|
|
|
+ Object userLock = userLocks.get(loginUser.getId(), Object::new);
|
|
|
synchronized (userLock) {
|
|
|
- // 0. 检查Redis缓存
|
|
|
String apiPath = httpRequest.getServletPath().split(BASE_PATH)[1]; // 获取TradeSparq API路径
|
|
|
String sortedParams =
|
|
|
requestBody.keySet().stream()
|
|
@@ -77,6 +80,7 @@ public class TradeSparqController {
|
|
|
.map(key -> FastJsonUtil.toJSONString(requestBody.get(key)))
|
|
|
.collect(Collectors.joining());
|
|
|
|
|
|
+ // 0. 检查Redis缓存
|
|
|
String redisKey =
|
|
|
String.format(
|
|
|
"tradesparq:%s:%s",
|
|
@@ -84,8 +88,9 @@ public class TradeSparqController {
|
|
|
JSONObject cachedResult = (JSONObject) adwebRedisUtil.get(redisKey);
|
|
|
if (Objects.nonNull(cachedResult)) {
|
|
|
log.info(
|
|
|
- "TradeSparq API返回Redis缓存数据,uid = {}, path = {}, request body = {}",
|
|
|
- uid,
|
|
|
+ "TradeSparq返回Redis缓存数据,uid = {}, name = {}, path = {}, request body = {}",
|
|
|
+ loginUser.getId(),
|
|
|
+ loginUser.getUsername(),
|
|
|
apiPath,
|
|
|
requestBody);
|
|
|
return Result.ok(cachedResult);
|
|
@@ -95,9 +100,9 @@ public class TradeSparqController {
|
|
|
boolean isQuotaLimited = this.isQuotaLimited(httpRequest, requestBody);
|
|
|
if (isQuotaLimited) {
|
|
|
Pair<Integer, Integer> customsDataQuota =
|
|
|
- resourceQuotaService.getCustomsDataQuota(uid);
|
|
|
+ resourceQuotaService.getCustomsDataQuota(loginUser.getId());
|
|
|
if (customsDataQuota.getLeft() <= customsDataQuota.getRight()) {
|
|
|
- log.warn("用户 {} 海关查询资源额度不足", uid);
|
|
|
+ log.warn("用户 {} {} 海关查询资源额度不足", loginUser.getId(), loginUser.getUsername());
|
|
|
return Result.error(
|
|
|
String.format(
|
|
|
"查询失败。用户资源额度为%d,已使用%d",
|
|
@@ -118,14 +123,15 @@ public class TradeSparqController {
|
|
|
ResponseEntity<JSONObject> responseEntity =
|
|
|
restTemplate.exchange(requestEntity, JSONObject.class);
|
|
|
log.info(
|
|
|
- "TradeSparq API调用成功,uid = {}, path = {}, request body = {}",
|
|
|
- uid,
|
|
|
+ "TradeSparq API调用成功,uid = {}, name = {}, path = {}, request body = {}",
|
|
|
+ loginUser.getId(),
|
|
|
+ loginUser.getUsername(),
|
|
|
apiPath,
|
|
|
requestBody);
|
|
|
|
|
|
// 3.1 记录资源额度消耗
|
|
|
if (isQuotaLimited) {
|
|
|
- resourceQuotaService.consumeCustomsDataQuota(uid);
|
|
|
+ resourceQuotaService.consumeCustomsDataQuota(loginUser.getId());
|
|
|
}
|
|
|
|
|
|
// 3.2 缓存到Redis,TTL为3小时
|
|
@@ -134,8 +140,9 @@ public class TradeSparqController {
|
|
|
return Result.ok(responseEntity.getBody());
|
|
|
} catch (RestClientResponseException e) {
|
|
|
log.error(
|
|
|
- "TradeSparq API调用失败,uid = {}, path = {}, request body = {}",
|
|
|
- uid,
|
|
|
+ "TradeSparq API调用失败,uid = {}, name = {}, path = {}, request body = {}",
|
|
|
+ loginUser.getId(),
|
|
|
+ loginUser.getUsername(),
|
|
|
apiPath,
|
|
|
requestBody,
|
|
|
e);
|
|
@@ -144,33 +151,6 @@ public class TradeSparqController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // TODO 暂无GET请求调用 - 待Redis缓存 + 额度控制
|
|
|
- // @GetMapping("/**")
|
|
|
- // @ResponseBody
|
|
|
- public Result<JSONObject> forwardGet(HttpServletRequest httpRequest) {
|
|
|
- // 1. 生成签名
|
|
|
- String apiPath = httpRequest.getServletPath().split(BASE_PATH)[1]; // 获取TradeSparq API路径
|
|
|
- String queryString = httpRequest.getQueryString();
|
|
|
- String apiUrl =
|
|
|
- String.format(
|
|
|
- "%s%s%s",
|
|
|
- apiHost,
|
|
|
- apiPath,
|
|
|
- StringUtils.isNotBlank(queryString) ? "?" + queryString : "");
|
|
|
- String sign = DigestUtils.md5DigestAsHex((apiSecret + apiUrl).getBytes());
|
|
|
-
|
|
|
- // 2. 构建并发送GET请求
|
|
|
- RequestEntity<?> requestEntity =
|
|
|
- RequestEntity.get(apiUrl).headers(this.getHttpHeaders(sign)).build();
|
|
|
- try {
|
|
|
- ResponseEntity<JSONObject> responseEntity =
|
|
|
- restTemplate.exchange(requestEntity, JSONObject.class);
|
|
|
- return Result.ok(responseEntity.getBody());
|
|
|
- } catch (RestClientResponseException e) {
|
|
|
- return Result.error(e.getStatusCode().value(), e.getMessage());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
private HttpHeaders getHttpHeaders(String sign) {
|
|
|
HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|