package org.springblade.core.boot.logger; 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.reflect.MethodSignature; import org.springblade.core.tool.jackson.JsonUtil; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.ClassUtil; import org.springblade.core.tool.utils.StringUtil; import org.springblade.core.tool.utils.WebUtil; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.MethodParameter; import org.springframework.core.io.InputStreamSource; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.request.WebRequest; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.TimeUnit; /** * Spring boot 控制器 请求日志,方便代码调试 * * @author L.cm */ @Slf4j @Aspect @Configuration @Profile({"dev", "test"}) public class RequestLogAspect { /** * AOP 环切 控制器 R 返回值 * @param point JoinPoint * @throws Throwable 异常 * @return Object */ @Around( "execution(!static org.springblade.core.tool.api.R<*> *(..)) && " + "(@within(org.springframework.stereotype.Controller) || " + "@within(org.springframework.web.bind.annotation.RestController))" ) public Object aroundApi(ProceedingJoinPoint point) throws Throwable { MethodSignature ms = (MethodSignature) point.getSignature(); Method method = ms.getMethod(); Object[] args = point.getArgs(); // 请求参数处理 final Map paraMap = new HashMap<>(16); for (int i = 0; i < args.length; i++) { // 读取方法参数 MethodParameter methodParam = ClassUtil.getMethodParameter(method, i); // PathVariable 参数跳过 PathVariable pathVariable = methodParam.getParameterAnnotation(PathVariable.class); if (pathVariable != null) { continue; } RequestBody requestBody = methodParam.getParameterAnnotation(RequestBody.class); Object object = args[i]; // 如果是body的json则是对象 if (requestBody != null && object != null) { paraMap.putAll(BeanUtil.toMap(object)); } else { // 参数名 RequestParam requestParam = methodParam.getParameterAnnotation(RequestParam.class); String paraName; if (requestParam != null && StringUtil.isNotBlank(requestParam.value())) { paraName = requestParam.value(); } else { paraName = methodParam.getParameterName(); } paraMap.put(paraName, object); } } HttpServletRequest request = WebUtil.getRequest(); String requestURI = request.getRequestURI(); String requestMethod = request.getMethod(); // 处理 参数 List needRemoveKeys = new ArrayList<>(paraMap.size()); paraMap.forEach((key, value) -> { if (value instanceof HttpServletRequest) { needRemoveKeys.add(key); paraMap.putAll(((HttpServletRequest) value).getParameterMap()); } else if (value instanceof HttpServletResponse) { needRemoveKeys.add(key); } else if (value instanceof InputStream) { needRemoveKeys.add(key); } else if (value instanceof MultipartFile) { String fileName = ((MultipartFile) value).getOriginalFilename(); paraMap.put(key, fileName); } else if (value instanceof InputStreamSource) { needRemoveKeys.add(key); } else if (value instanceof WebRequest) { needRemoveKeys.add(key); paraMap.putAll(((WebRequest) value).getParameterMap()); } }); needRemoveKeys.forEach(paraMap::remove); // 打印请求 if (paraMap.isEmpty()) { log.info("===> {}: {}", requestMethod, requestURI); } else { log.info("===> {}: {} Parameters: {}", requestMethod, requestURI, JsonUtil.toJson(paraMap)); } // 打印请求头 Enumeration headers = request.getHeaderNames(); while (headers.hasMoreElements()) { String headerName = headers.nextElement(); String headerValue = request.getHeader(headerName); log.info("===headers=== {} : {}", headerName, headerValue); } // 打印执行时间 long startNs = System.nanoTime(); try { Object result = point.proceed(); log.info("===Result=== {}", JsonUtil.toJson(result)); return result; } finally { long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); log.info("<=== {}: {} ({} ms)", request.getMethod(), requestURI, tookMs); } } }