springboot增加请求响应日志类
一、修改yml配置文件
logging: includePaths: - /** - /api/**
二、增加配置类
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.List; /** * @author fengyi */ @Component @ConfigurationProperties(prefix = "logging") public class LoggingProperties { private List<String> includePaths; public List<String> getIncludePaths() { return includePaths; } public void setIncludePaths(List<String> includePaths) { this.includePaths = includePaths; } }
三、编写日志切面类
import cn.hutool.json.JSONUtil; import com.beauty.framework.config.LoggingProperties; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.support.MultipartFilter; import javax.annotation.Resource; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * @author fengyi */ @Slf4j @Aspect @Component public class WhiteListLogAspect { @Resource private LoggingProperties loggingProperties; private AntPathMatcher pathMatcher = new AntPathMatcher(); private Long startTime; @AfterReturning(pointcut = "execution(* com.beauty.*.controller..*(..))", returning = "result") public void doAfterReturning(JoinPoint joinPoint, Object result) { // 获取请求信息 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String requestURI = request.getRequestURI(); if (shouldLog(requestURI)) { // 将处理结果转换为JSON字符串,这里假设返回类型可以被JSONUtil.toJsonStr处理 String responseJson = JSONUtil.toJsonStr(result); addLog(joinPoint, responseJson, System.currentTimeMillis() - startTime); } } @Before("execution(* com.beauty.*.controller..*(..))") public void doBefore(JoinPoint joinPoint) { startTime = System.currentTimeMillis(); } /** * 日志记录入库操作 */ public void addLog(JoinPoint joinPoint, String outParams, long time) { HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); log.info("\n\r=======================================\n\r" + "请求地址:{} \n\r" + "请求方式:{} \n\r" + "请求参数:{} \n\r" + "请求体:{} \n\r" + "请求类方法:{} \n\r" + "请求方法参数:{} \n\r" + "返回报文:{} \n\r" + "处理耗时:{} ms \n\r" + "=======================================\n\r", request.getRequestURI(), request.getMethod(), request.getQueryString(), this.getBody(request), joinPoint.getSignature(), JSONUtil.toJsonStr(filterArgs(joinPoint.getArgs())), outParams, time ); } /** * 解析请求体 * * @param request * @return */ public String getBody(HttpServletRequest request) { int contentLength = request.getContentLength(); if (contentLength < 0) { return StringUtils.EMPTY; } byte[] bytes = new byte[contentLength]; try { ServletInputStream inputStream = request.getInputStream(); inputStream.read(bytes); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } return new String(bytes, 0, contentLength, StandardCharsets.UTF_8); } /** * 过滤参数 * * @param args * @return */ private List<Object> filterArgs(Object[] args) { return Arrays.stream(args).filter(object -> !(object instanceof MultipartFilter) && !(object instanceof HttpServletRequest) && !(object instanceof HttpServletResponse) ).collect(Collectors.toList()); } /** * 判断路径是否需要记录日志 * * @param requestURI * @return */ private boolean shouldLog(String requestURI) { return loggingProperties.getIncludePaths().stream().anyMatch(pattern -> pathMatcher.match(pattern, requestURI)); } }