package com.qianwen.core.log.aspect; import java.io.InputStream; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import com.qianwen.core.launch.log.BladeLogLevel; import com.qianwen.core.log.props.BladeRequestLogProperties; import com.qianwen.core.tool.jackson.JsonUtil; import com.qianwen.core.tool.utils.ClassUtil; import com.qianwen.core.tool.utils.StringUtil; import com.qianwen.core.tool.utils.WebUtil; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.context.annotation.Configuration; 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; @Aspect @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = {"blade.log.request.enabled"}, havingValue = "true", matchIfMissing = true) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) /* loaded from: blade-starter-log-9.3.0.0-SNAPSHOT.jar:org/springblade/core/log/aspect/RequestLogAspect.class */ public class RequestLogAspect { private static final Logger log = LoggerFactory.getLogger(RequestLogAspect.class); private final BladeRequestLogProperties properties; public RequestLogAspect(final BladeRequestLogProperties properties) { this.properties = properties; } @Around("execution(!static com.qianwen.core.tool.api.R *(..)) && (@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController))") public Object aroundApi(ProceedingJoinPoint point) throws Throwable { BladeLogLevel level = this.properties.getLevel(); if (BladeLogLevel.NONE == level) { return point.proceed(); } HttpServletRequest request = WebUtil.getRequest(); Object requestUrl = ((HttpServletRequest) Objects.requireNonNull(request)).getRequestURI(); Object requestMethod = request.getMethod(); StringBuilder beforeReqLog = new StringBuilder(300); List beforeReqArgs = new ArrayList<>(); beforeReqLog.append("\n\n================ Request Start ================\n"); beforeReqLog.append("===> {}: {}"); beforeReqArgs.add(requestMethod); beforeReqArgs.add(requestUrl); logIngArgs(point, beforeReqLog, beforeReqArgs); logIngHeaders(request, level, beforeReqLog, beforeReqArgs); beforeReqLog.append("================ Request End ================\n"); long startNs = System.nanoTime(); log.info(beforeReqLog.toString(), beforeReqArgs.toArray()); StringBuilder afterReqLog = new StringBuilder(200); List afterReqArgs = new ArrayList<>(); afterReqLog.append("\n\n=============== Response Start ================\n"); try { Object result = point.proceed(); if (BladeLogLevel.BODY.lte(level)) { afterReqLog.append("===Result=== {}\n"); afterReqArgs.add(JsonUtil.toJson(result)); } long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); afterReqLog.append("<=== {}: {} ({} ms)\n"); afterReqArgs.add(requestMethod); afterReqArgs.add(requestUrl); afterReqArgs.add(Long.valueOf(tookMs)); afterReqLog.append("=============== Response End ================\n"); log.info(afterReqLog.toString(), afterReqArgs.toArray()); return result; } catch (Throwable th) { long tookMs2 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); afterReqLog.append("<=== {}: {} ({} ms)\n"); afterReqArgs.add(requestMethod); afterReqArgs.add(requestUrl); afterReqArgs.add(Long.valueOf(tookMs2)); afterReqLog.append("=============== Response End ================\n"); log.info(afterReqLog.toString(), afterReqArgs.toArray()); throw th; } } public void logIngArgs(ProceedingJoinPoint point, StringBuilder beforeReqLog, List beforeReqArgs) { MethodSignature ms = (MethodSignature)point.getSignature(); Method method = ms.getMethod(); Object[] args = point.getArgs(); Map paraMap = new HashMap<>(16); Object requestBodyValue = null; 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 = (RequestBody)methodParam.getParameterAnnotation(RequestBody.class); String parameterName = methodParam.getParameterName(); Object value = args[i]; if (requestBody != null) { requestBodyValue = value; continue; } if (value instanceof HttpServletRequest) { paraMap.putAll(((HttpServletRequest)value).getParameterMap()); continue; } if (value instanceof WebRequest) { paraMap.putAll(((WebRequest)value).getParameterMap()); continue; } if (value instanceof javax.servlet.http.HttpServletResponse) continue; if (value instanceof MultipartFile) { MultipartFile multipartFile = (MultipartFile)value; String name = multipartFile.getName(); String fileName = multipartFile.getOriginalFilename(); paraMap.put(name, fileName); continue; } if (value instanceof MultipartFile[]) { MultipartFile[] arr = (MultipartFile[])value; if (arr.length != 0) { String name = arr[0].getName(); StringBuilder sb = new StringBuilder(arr.length); for (MultipartFile multipartFile : arr) { sb.append(multipartFile.getOriginalFilename()); sb.append(","); } paraMap.put(name, StringUtil.removeSuffix(sb.toString(), ",")); } continue; } if (value instanceof List) { List list = (List)value; AtomicBoolean isSkip = new AtomicBoolean(false); for (Object o : list) { if ("StandardMultipartFile".equalsIgnoreCase(o.getClass().getSimpleName())) { isSkip.set(true); break; } } if (isSkip.get()) { paraMap.put(parameterName, "此参数不能序列化为json"); continue; } } RequestParam requestParam = (RequestParam)methodParam.getParameterAnnotation(RequestParam.class); String paraName = parameterName; if (requestParam != null && StringUtil.isNotBlank(requestParam.value())) paraName = requestParam.value(); if (value == null) { paraMap.put(paraName, null); } else if (ClassUtil.isPrimitiveOrWrapper(value.getClass())) { paraMap.put(paraName, value); } else if (value instanceof java.io.InputStream) { paraMap.put(paraName, "InputStream"); } else if (value instanceof org.springframework.core.io.InputStreamSource) { paraMap.put(paraName, "InputStreamSource"); } else if (JsonUtil.canSerialize(value)) { paraMap.put(paraName, value); } else { paraMap.put(paraName, "此参数不能序列化为json"); } } if (paraMap.isEmpty()) { beforeReqLog.append("\n"); } else { beforeReqLog.append(" Parameters: {}\n"); beforeReqArgs.add(JsonUtil.toJson(paraMap)); } if (requestBodyValue != null) { beforeReqLog.append("====Body===== {}\n"); beforeReqArgs.add(JsonUtil.toJson(requestBodyValue)); } } public void logIngHeaders(HttpServletRequest request, BladeLogLevel level, StringBuilder beforeReqLog, List beforeReqArgs) { if (BladeLogLevel.HEADERS.lte(level)) { Enumeration headers = request.getHeaderNames(); while (headers.hasMoreElements()) { String headerName = headers.nextElement(); String headerValue = request.getHeader(headerName); beforeReqLog.append("===Headers=== {}: {}\n"); beforeReqArgs.add(headerName); beforeReqArgs.add(headerValue); } } } }