package com.poyee.aspect.weblog; import cn.hutool.json.JSONUtil; import com.poyee.utils.ServletUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.slf4j.MDC; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * 统一日志处理切面 */ @Aspect @Component @Order(1) public class WebLogAspect { private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class); @Pointcut("execution(public * com.poyee.controller..*.*(..))") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) { HttpServletRequest request = ServletUtils.getRequest(); String traceId = Objects.requireNonNull(request).getHeader("X-Trace-Id"); if (!StringUtils.hasText(traceId)) { traceId = UUID.randomUUID().toString().replace("-", ""); } MDC.put("traceId", traceId); long currentTimeMillis = System.currentTimeMillis(); String requestURI = request.getRequestURI(); RequestNoContext.callTime.set(currentTimeMillis); RequestNoContext.apiUrl.set(requestURI); RequestNoContext.currentThreadId.set(currentTimeMillis); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); String argsJson = JSONUtil.toJsonStr(getParameter(method, joinPoint.getArgs())); RequestNoContext.requestParam.set(argsJson); String log = "\n===============[" + RequestNoContext.currentThreadId.get() + "]请求内容开始===============" + "\n 请求地址:" + requestURI + "\n 请求方式:" + request.getMethod() + "\n 客户端 IP:" + request.getRemoteAddr() + "\n 接口参数:" + argsJson + "\n===============[" + RequestNoContext.currentThreadId.get() + "]请求内容结束==============="; logger.info(log); } @AfterReturning(value = "webLog()", returning = "returns") public void afterReturning(Object returns) { long costTime = System.currentTimeMillis() - RequestNoContext.callTime.get(); logger.info("\n--------------[{}]返回内容开始----------------\n 接口地址:{}\n 返回内容:{}\n 请求耗时:{}ms\n--------------[{}]返回内容结束----------------", RequestNoContext.currentThreadId.get(), RequestNoContext.apiUrl.get(), JSONUtil.toJsonStr(returns), costTime, RequestNoContext.currentThreadId.get()); RequestNoContext.remove(); MDC.remove("traceId"); } @AfterThrowing(value = "webLog()", throwing = "e") public void throwing(Throwable e) { HttpServletRequest request = ServletUtils.getRequest(); long costTime = System.currentTimeMillis() - RequestNoContext.callTime.get(); logger.error("\n--------------[{}]返回内容开始----------------\n 接口地址:{}\n 请求令牌:{}\n 接口参数:{}\n 请求失败:{}\n 请求耗时:{}ms\n--------------[{}]返回内容结束----------------", RequestNoContext.currentThreadId.get(), RequestNoContext.apiUrl.get(), Objects.requireNonNull(request).getHeader("Authorization"), RequestNoContext.requestParam.get(), e.getMessage(), costTime, RequestNoContext.currentThreadId.get()); RequestNoContext.remove(); MDC.remove("traceId"); } /** * 根据方法和传入的参数获取请求参数 */ private Object getParameter(Method method, Object[] args) { Parameter[] parameters = method.getParameters(); List argList = IntStream.range(0, parameters.length) .mapToObj(i -> { Parameter parameter = parameters[i]; RequestBody requestBody = parameter.getAnnotation(RequestBody.class); if (requestBody != null) { return args[i]; } RequestParam requestParam = parameter.getAnnotation(RequestParam.class); if (requestParam != null) { Map map = new HashMap<>(); String key = StringUtils.hasText(requestParam.value()) ? requestParam.value() : parameter.getName(); map.put(key, args[i]); return map; } return null; }) .filter(Objects::nonNull) .collect(Collectors.toList()); if (argList.isEmpty()) { return null; } else if (argList.size() == 1) { return argList.get(0); } else { return argList; } } }