package com.supervision.config; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.util.ObjectUtils; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; import java.util.Map; /** * 日志切面 * * @author :liu * create :2020-11-16 10:50 **/ @Component @Aspect @Slf4j public class RequestLogConfig { @SuppressWarnings("all") @Around("within(com..*..controller..*) && @within(org.springframework.web.bind.annotation.RestController)") public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { long start = System.currentTimeMillis(); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); Object result = proceedingJoinPoint.proceed(); RequestInfo requestInfo = new RequestInfo(); requestInfo.setUrl(request.getRequestURL().toString()); requestInfo.setHttpMethod(request.getMethod()); requestInfo.setClassMethod(String.format("%s.%s", proceedingJoinPoint.getSignature().getDeclaringTypeName(), proceedingJoinPoint.getSignature().getName())); requestInfo.setRequestParams(getRequestParamsByProceedingJoinPoint(proceedingJoinPoint)); requestInfo.setResult(proceedResult(result)); requestInfo.setTimeCost(System.currentTimeMillis() - start); log.info("Request Info: {}", JSONUtil.toJsonStr(requestInfo)); return result; } private Object proceedResult(Object result) { String value = null; try { value = JSONUtil.toJsonStr(result); } catch (Exception e) { value = result.toString(); } if (StrUtil.isNotBlank(value) && value.length() > 10240){ value = value.substring(0, 1024) + "......" + value.substring(value.length() - 1024); return value; } return result; } @SuppressWarnings("all") @AfterThrowing(pointcut = "@within(org.springframework.web.bind.annotation.RestController)", throwing = "e") public void doAfterThrow(JoinPoint joinPoint, RuntimeException e) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); RequestErrorInfo requestErrorInfo = new RequestErrorInfo(); requestErrorInfo.setUrl(request.getRequestURL().toString()); requestErrorInfo.setHttpMethod(request.getMethod()); requestErrorInfo.setClassMethod(String.format("%s.%s", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName())); requestErrorInfo.setRequestParams(getRequestParamsByJoinPoint(joinPoint)); requestErrorInfo.setException(e); log.info("Error Request Info : {}", JSONUtil.toJsonStr(requestErrorInfo)); } /** * 获取入参 * * @param proceedingJoinPoint * @return */ private Map getRequestParamsByProceedingJoinPoint(ProceedingJoinPoint proceedingJoinPoint) { //参数名 String[] paramNames = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterNames(); //参数值 Object[] paramValues = proceedingJoinPoint.getArgs(); return buildRequestParam(paramNames, paramValues); } private Map getRequestParamsByJoinPoint(JoinPoint joinPoint) { //参数名 String[] paramNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); //参数值 Object[] paramValues = joinPoint.getArgs(); return buildRequestParam(paramNames, paramValues); } private Map buildRequestParam(String[] paramNames, Object[] paramValues) { Map requestParams = new HashMap<>(); for (int i = 0; i < paramNames.length; i++) { Object value = paramValues[i]; if (value instanceof ServletRequest || value instanceof ServletResponse) { //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false) //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response continue; } //如果是文件对象 if (value instanceof MultipartFile) { MultipartFile file = (MultipartFile) value; //获取文件名 value = file.getOriginalFilename(); } else if (value instanceof String) { // 如果参数很长,就对参数进行修剪 String temp = (String) value; if (!ObjectUtils.isEmpty(temp) && temp.length() > 1024) { value = temp.substring(0, 10) + "......" + temp.substring(temp.length() - 10); } } requestParams.put(paramNames[i], value); } return requestParams; } @Data public static class RequestInfo { private String url; private String httpMethod; private String classMethod; private Object requestParams; private Object result; private Long timeCost; } @Data public static class RequestErrorInfo { private String url; private String httpMethod; private String classMethod; private Object requestParams; private RuntimeException exception; } }