package com.zsElectric.boot.charging.aspect; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.zsElectric.boot.charging.entity.ThirdPartyApiLog; import com.zsElectric.boot.charging.service.ThirdPartyApiLogService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.time.LocalDateTime; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; /** * 第三方接口日志记录切面 * 拦截 LinkDataController 和 ChargingBusinessController 的所有方法,自动记录请求和响应日志 * * @author system * @since 2025-01-02 */ @Slf4j @Aspect @Component @RequiredArgsConstructor public class ThirdPartyApiLogAspect { private final ThirdPartyApiLogService thirdPartyApiLogService; private final ObjectMapper objectMapper; /** * 定义切入点: LinkDataController 的所有方法 */ @Pointcut("execution(* com.zsElectric.boot.charging.controller.LinkDataController.*(..))") public void linkDataControllerPointcut() { } /** * 定义切入点: ChargingBusinessController 的所有方法 */ @Pointcut("execution(* com.zsElectric.boot.charging.controller.ChargingBusinessController.*(..))") public void chargingBusinessControllerPointcut() { } /** * 环绕通知: 记录 LinkDataController 接口日志 */ @Around("linkDataControllerPointcut()") public Object aroundLinkDataController(ProceedingJoinPoint joinPoint) throws Throwable { return recordApiLog(joinPoint, "LinkDataController", 2); // 2-接收推送 } /** * 环绕通知: 记录 ChargingBusinessController 接口日志 */ @Around("chargingBusinessControllerPointcut()") public Object aroundChargingBusinessController(ProceedingJoinPoint joinPoint) throws Throwable { return recordApiLog(joinPoint, "ChargingBusinessController", 1); // 1-请求出去 } /** * 记录接口日志的通用方法 */ private Object recordApiLog(ProceedingJoinPoint joinPoint, String controllerName, Integer logType) throws Throwable { long startTime = System.currentTimeMillis(); ThirdPartyApiLog apiLog = new ThirdPartyApiLog(); // 获取 HttpServletRequest ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes != null ? attributes.getRequest() : null; try { // 设置基本信息 apiLog.setLogType(logType); apiLog.setControllerName(controllerName); LocalDateTime now = LocalDateTime.now(); apiLog.setCreatedTime(now); apiLog.setUpdatedTime(now); if (request != null) { // 请求信息 apiLog.setRequestMethod(request.getMethod()); apiLog.setRequestUrl(request.getRequestURL().toString()); apiLog.setInterfaceName(request.getRequestURI()); apiLog.setClientIp(getClientIp(request)); apiLog.setUserAgent(request.getHeader("User-Agent")); // 请求头 apiLog.setRequestHeaders(getRequestHeaders(request)); // 请求参数 Map parameterMap = request.getParameterMap(); if (!parameterMap.isEmpty()) { apiLog.setRequestParams(objectMapper.writeValueAsString(parameterMap)); } // 请求体(从切点参数中获取) Object[] args = joinPoint.getArgs(); if (args != null && args.length > 0) { for (Object arg : args) { if (arg != null && !(arg instanceof HttpServletRequest) && !(arg instanceof jakarta.servlet.http.HttpServletResponse)) { apiLog.setRequestBody(objectMapper.writeValueAsString(arg)); // 尝试提取业务字段 extractBusinessFields(arg, apiLog); break; } } } } // 执行目标方法 Object result = joinPoint.proceed(); // 记录响应 long endTime = System.currentTimeMillis(); apiLog.setResponseTime(endTime - startTime); apiLog.setResponseStatus(200); apiLog.setIsSuccess(1); if (result != null) { apiLog.setResponseBody(objectMapper.writeValueAsString(result)); } // 异步保存日志 thirdPartyApiLogService.saveLogAsync(apiLog); return result; } catch (Exception e) { // 记录异常 long endTime = System.currentTimeMillis(); apiLog.setResponseTime(endTime - startTime); apiLog.setResponseStatus(500); apiLog.setIsSuccess(0); apiLog.setErrorMessage(e.getMessage()); // 异步保存日志 thirdPartyApiLogService.saveLogAsync(apiLog); throw e; } } /** * 提取业务字段 */ private void extractBusinessFields(Object requestBody, ThirdPartyApiLog apiLog) { try { String json = objectMapper.writeValueAsString(requestBody); Map map = objectMapper.readValue(json, Map.class); // 提取运营商ID if (map.containsKey("OperatorID")) { apiLog.setOperatorId(String.valueOf(map.get("OperatorID"))); } else if (map.containsKey("operatorID")) { apiLog.setOperatorId(String.valueOf(map.get("operatorID"))); } // 提取充电站ID if (map.containsKey("StationID")) { apiLog.setStationId(String.valueOf(map.get("StationID"))); } else if (map.containsKey("stationID")) { apiLog.setStationId(String.valueOf(map.get("stationID"))); } // 提取充电桩ID if (map.containsKey("ConnectorID")) { apiLog.setConnectorId(String.valueOf(map.get("ConnectorID"))); } else if (map.containsKey("connectorID")) { apiLog.setConnectorId(String.valueOf(map.get("connectorID"))); } // 提取业务流水号 if (map.containsKey("StartChargeSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("StartChargeSeq"))); } else if (map.containsKey("startChargeSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("startChargeSeq"))); } else if (map.containsKey("EquipAuthSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("EquipAuthSeq"))); } else if (map.containsKey("equipAuthSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("equipAuthSeq"))); } else if (map.containsKey("EquipBizSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("EquipBizSeq"))); } else if (map.containsKey("equipBizSeq")) { apiLog.setBusinessSeq(String.valueOf(map.get("equipBizSeq"))); } } catch (Exception e) { log.debug("提取业务字段失败: {}", e.getMessage()); } } /** * 获取请求头信息 */ private String getRequestHeaders(HttpServletRequest request) { try { Map headers = new HashMap<>(); Enumeration headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); headers.put(headerName, request.getHeader(headerName)); } return objectMapper.writeValueAsString(headers); } catch (Exception e) { log.error("获取请求头失败: {}", e.getMessage()); return null; } } /** * 获取客户端真实IP */ private String getClientIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (StrUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { // 多次反向代理后会有多个IP值,第一个为真实IP int index = ip.indexOf(','); if (index != -1) { return ip.substring(0, index); } return ip; } ip = request.getHeader("X-Real-IP"); if (StrUtil.isNotBlank(ip) && !"unknown".equalsIgnoreCase(ip)) { return ip; } return request.getRemoteAddr(); } }