ThirdPartyApiLogAspect.java 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package com.zsElectric.boot.charging.aspect;
  2. import cn.hutool.core.util.StrUtil;
  3. import cn.hutool.json.JSONUtil;
  4. import com.fasterxml.jackson.databind.ObjectMapper;
  5. import com.zsElectric.boot.charging.entity.ThirdPartyApiLog;
  6. import com.zsElectric.boot.charging.service.ThirdPartyApiLogService;
  7. import jakarta.servlet.http.HttpServletRequest;
  8. import lombok.RequiredArgsConstructor;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.aspectj.lang.ProceedingJoinPoint;
  11. import org.aspectj.lang.annotation.Around;
  12. import org.aspectj.lang.annotation.Aspect;
  13. import org.aspectj.lang.annotation.Pointcut;
  14. import org.springframework.stereotype.Component;
  15. import org.springframework.web.context.request.RequestContextHolder;
  16. import org.springframework.web.context.request.ServletRequestAttributes;
  17. import java.time.LocalDateTime;
  18. import java.util.Enumeration;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. /**
  22. * 第三方接口日志记录切面
  23. * 拦截 LinkDataController 和 ChargingBusinessController 的所有方法,自动记录请求和响应日志
  24. *
  25. * @author system
  26. * @since 2025-01-02
  27. */
  28. @Slf4j
  29. @Aspect
  30. @Component
  31. @RequiredArgsConstructor
  32. public class ThirdPartyApiLogAspect {
  33. private final ThirdPartyApiLogService thirdPartyApiLogService;
  34. private final ObjectMapper objectMapper;
  35. /**
  36. * 定义切入点: LinkDataController 的所有方法
  37. */
  38. @Pointcut("execution(* com.zsElectric.boot.charging.controller.LinkDataController.*(..))")
  39. public void linkDataControllerPointcut() {
  40. }
  41. /**
  42. * 定义切入点: ChargingBusinessController 的所有方法
  43. */
  44. @Pointcut("execution(* com.zsElectric.boot.charging.controller.ChargingBusinessController.*(..))")
  45. public void chargingBusinessControllerPointcut() {
  46. }
  47. /**
  48. * 环绕通知: 记录 LinkDataController 接口日志
  49. */
  50. @Around("linkDataControllerPointcut()")
  51. public Object aroundLinkDataController(ProceedingJoinPoint joinPoint) throws Throwable {
  52. return recordApiLog(joinPoint, "LinkDataController", 2); // 2-接收推送
  53. }
  54. /**
  55. * 环绕通知: 记录 ChargingBusinessController 接口日志
  56. */
  57. @Around("chargingBusinessControllerPointcut()")
  58. public Object aroundChargingBusinessController(ProceedingJoinPoint joinPoint) throws Throwable {
  59. return recordApiLog(joinPoint, "ChargingBusinessController", 1); // 1-请求出去
  60. }
  61. /**
  62. * 记录接口日志的通用方法
  63. */
  64. private Object recordApiLog(ProceedingJoinPoint joinPoint, String controllerName, Integer logType) throws Throwable {
  65. long startTime = System.currentTimeMillis();
  66. ThirdPartyApiLog apiLog = new ThirdPartyApiLog();
  67. // 获取 HttpServletRequest
  68. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  69. HttpServletRequest request = attributes != null ? attributes.getRequest() : null;
  70. try {
  71. // 设置基本信息
  72. apiLog.setLogType(logType);
  73. apiLog.setControllerName(controllerName);
  74. LocalDateTime now = LocalDateTime.now();
  75. apiLog.setCreatedTime(now);
  76. apiLog.setUpdatedTime(now);
  77. if (request != null) {
  78. // 请求信息
  79. apiLog.setRequestMethod(request.getMethod());
  80. apiLog.setRequestUrl(request.getRequestURL().toString());
  81. apiLog.setInterfaceName(request.getRequestURI());
  82. apiLog.setClientIp(getClientIp(request));
  83. apiLog.setUserAgent(request.getHeader("User-Agent"));
  84. // 请求头
  85. apiLog.setRequestHeaders(getRequestHeaders(request));
  86. // 请求参数
  87. Map<String, String[]> parameterMap = request.getParameterMap();
  88. if (!parameterMap.isEmpty()) {
  89. apiLog.setRequestParams(objectMapper.writeValueAsString(parameterMap));
  90. }
  91. // 请求体(从切点参数中获取)
  92. Object[] args = joinPoint.getArgs();
  93. if (args != null && args.length > 0) {
  94. for (Object arg : args) {
  95. if (arg != null && !(arg instanceof HttpServletRequest) && !(arg instanceof jakarta.servlet.http.HttpServletResponse)) {
  96. apiLog.setRequestBody(objectMapper.writeValueAsString(arg));
  97. // 尝试提取业务字段
  98. extractBusinessFields(arg, apiLog);
  99. break;
  100. }
  101. }
  102. }
  103. }
  104. // 执行目标方法
  105. Object result = joinPoint.proceed();
  106. // 记录响应
  107. long endTime = System.currentTimeMillis();
  108. apiLog.setResponseTime(endTime - startTime);
  109. apiLog.setResponseStatus(200);
  110. apiLog.setIsSuccess(1);
  111. if (result != null) {
  112. apiLog.setResponseBody(objectMapper.writeValueAsString(result));
  113. }
  114. // 异步保存日志
  115. thirdPartyApiLogService.saveLogAsync(apiLog);
  116. return result;
  117. } catch (Exception e) {
  118. // 记录异常
  119. long endTime = System.currentTimeMillis();
  120. apiLog.setResponseTime(endTime - startTime);
  121. apiLog.setResponseStatus(500);
  122. apiLog.setIsSuccess(0);
  123. apiLog.setErrorMessage(e.getMessage());
  124. // 异步保存日志
  125. thirdPartyApiLogService.saveLogAsync(apiLog);
  126. throw e;
  127. }
  128. }
  129. /**
  130. * 提取业务字段
  131. */
  132. private void extractBusinessFields(Object requestBody, ThirdPartyApiLog apiLog) {
  133. try {
  134. String json = objectMapper.writeValueAsString(requestBody);
  135. Map<String, Object> map = objectMapper.readValue(json, Map.class);
  136. // 提取运营商ID
  137. if (map.containsKey("OperatorID")) {
  138. apiLog.setOperatorId(String.valueOf(map.get("OperatorID")));
  139. } else if (map.containsKey("operatorID")) {
  140. apiLog.setOperatorId(String.valueOf(map.get("operatorID")));
  141. }
  142. // 提取充电站ID
  143. if (map.containsKey("StationID")) {
  144. apiLog.setStationId(String.valueOf(map.get("StationID")));
  145. } else if (map.containsKey("stationID")) {
  146. apiLog.setStationId(String.valueOf(map.get("stationID")));
  147. }
  148. // 提取充电桩ID
  149. if (map.containsKey("ConnectorID")) {
  150. apiLog.setConnectorId(String.valueOf(map.get("ConnectorID")));
  151. } else if (map.containsKey("connectorID")) {
  152. apiLog.setConnectorId(String.valueOf(map.get("connectorID")));
  153. }
  154. // 提取业务流水号
  155. if (map.containsKey("StartChargeSeq")) {
  156. apiLog.setBusinessSeq(String.valueOf(map.get("StartChargeSeq")));
  157. } else if (map.containsKey("startChargeSeq")) {
  158. apiLog.setBusinessSeq(String.valueOf(map.get("startChargeSeq")));
  159. } else if (map.containsKey("EquipAuthSeq")) {
  160. apiLog.setBusinessSeq(String.valueOf(map.get("EquipAuthSeq")));
  161. } else if (map.containsKey("equipAuthSeq")) {
  162. apiLog.setBusinessSeq(String.valueOf(map.get("equipAuthSeq")));
  163. } else if (map.containsKey("EquipBizSeq")) {
  164. apiLog.setBusinessSeq(String.valueOf(map.get("EquipBizSeq")));
  165. } else if (map.containsKey("equipBizSeq")) {
  166. apiLog.setBusinessSeq(String.valueOf(map.get("equipBizSeq")));
  167. }
  168. } catch (Exception e) {
  169. log.debug("提取业务字段失败: {}", e.getMessage());
  170. }
  171. }
  172. /**
  173. * 获取请求头信息
  174. */
  175. private String getRequestHeaders(HttpServletRequest request) {
  176. try {
  177. Map<String, String> headers = new HashMap<>();
  178. Enumeration<String> headerNames = request.getHeaderNames();
  179. while (headerNames.hasMoreElements()) {
  180. String headerName = headerNames.nextElement();
  181. headers.put(headerName, request.getHeader(headerName));
  182. }
  183. return objectMapper.writeValueAsString(headers);
  184. } catch (Exception e) {
  185. log.error("获取请求头失败: {}", e.getMessage());
  186. return null;
  187. }
  188. }
  189. /**
  190. * 获取客户端真实IP
  191. */
  192. private String getClientIp(HttpServletRequest request) {
  193. String ip = request.getHeader("X-Forwarded-For");
  194. if (StrUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
  195. // 多次反向代理后会有多个IP值,第一个为真实IP
  196. int index = ip.indexOf(',');
  197. if (index != -1) {
  198. return ip.substring(0, index);
  199. }
  200. return ip;
  201. }
  202. ip = request.getHeader("X-Real-IP");
  203. if (StrUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
  204. return ip;
  205. }
  206. return request.getRemoteAddr();
  207. }
  208. }