fix:AOP添加接口日志

This commit is contained in:
zhouz
2024-07-30 13:55:55 +08:00
parent 2525a8955e
commit 024d00bd37
8 changed files with 422 additions and 2 deletions

View File

@@ -0,0 +1,142 @@
package org.nl.modules.logging.aspect;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.nl.common.utils.SecurityUtils;
import org.nl.modules.common.utils.RequestHolder;
import org.nl.modules.common.utils.StringUtils;
import org.nl.modules.common.utils.ThrowableUtil;
import org.nl.modules.logging.properties.LoggingProperties;
import org.nl.system.service.logging.ISysInterfaceLogService;
import org.nl.system.service.logging.dao.SysInterfaceLog;
import org.nl.system.service.logging.dao.SysLog;
import org.springframework.beans.factory.annotation.Autowired;
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.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author by: zz
* @ClassName: WhiteListLogAspect
* @Description: 外部接口日志切面插入日志表
* @Date: 2024/7/25 15:06
*/
@Slf4j
@Aspect
@Component
public class WhiteListLogAspect {
@Autowired
private LoggingProperties loggingProperties;
@Autowired
private ISysInterfaceLogService interfaceLogService;
private AntPathMatcher pathMatcher = new AntPathMatcher();
@Pointcut("execution(* org.nl.wms.ext..*Service.*(..))")
public void logPointcut() {
// 该方法无方法体,主要为了让同类中其他方法使用此切入点
}
@Around("logPointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Object result = null;
try {
long startTime = System.currentTimeMillis();
result = joinPoint.proceed(args);
long endTime = System.currentTimeMillis();
long time = endTime - startTime;
addLog(joinPoint, JSONUtil.toJsonStr(result), time);
} catch (Exception e) {
log.error("doAround日志记录异常异常信息为:", e);
throw e;
}
return result;
}
/**
* 日志记录操作
*/
public void addLog(ProceedingJoinPoint joinPoint, String outParams, long time) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
HttpServletResponse response = attributes.getResponse();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 方法路径
String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
String[] split = joinPoint.getTarget().getClass().getName().split("\\.");
String className = split[split.length - 1];
StringUtils.getIp(request);
log.info("\n\r=======================================\n\r" +
"请求地址:{} \n\r" +
"请求方式:{} \n\r" +
"请求类方法:{} \n\r" +
"方法名::{} \n\r" +
"调用IP:{} \n\r" +
"接口名称:{} \n\r" +
"请求方法参数:{} \n\r" +
"返回报文:{} \n\r" +
"处理耗时:{} ms \n\r" +
"=======================================\n\r",
request.getRequestURI(),
request.getMethod(),
joinPoint.getSignature(),
className,
StringUtils.getIp(request),
signature.getName(),
JSONUtil.toJsonStr(filterArgs(joinPoint.getArgs())),
outParams,
time
);
SysInterfaceLog log = new SysInterfaceLog("INFO", time);
interfaceLogService.save(getUsername(), outParams, StringUtils.getBrowser(request), StringUtils.getIp(request), joinPoint, log);
}
public String getUsername() {
try {
return SecurityUtils.getCurrentUsername();
} catch (Exception e) {
return "";
}
}
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
SysInterfaceLog log = new SysInterfaceLog("ERROR", 0L);
log.setException_detail(ThrowableUtil.getStackTrace(e).getBytes());
HttpServletRequest request = RequestHolder.getHttpServletRequest();
interfaceLogService.save(getUsername(), e.toString(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint) joinPoint, log);
}
/**
* 过滤参数
*
* @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());
}
}

View File

@@ -0,0 +1,22 @@
package org.nl.modules.logging.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
@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;
}
}

View File

@@ -0,0 +1,21 @@
package org.nl.system.service.logging;
import com.baomidou.mybatisplus.extension.service.IService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.nl.system.service.logging.dao.SysInterfaceLog;
import org.nl.system.service.logging.dao.SysLog;
import org.springframework.scheduling.annotation.Async;
/**
* <p>
* 系统日志表 服务类
* </p>
*
* @author author
* @since 2024-07-29
*/
public interface ISysInterfaceLogService extends IService<SysInterfaceLog> {
@Async
void save(String username, String outParam, String browser, String ip, ProceedingJoinPoint joinPoint, SysInterfaceLog log);
}

View File

@@ -0,0 +1,113 @@
package org.nl.system.service.logging.dao;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* <p>
* 系统日志表
* </p>
*
* @author author
* @since 2024-07-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@TableName("sys_interface_log")
public class SysInterfaceLog implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 标识
*/
@TableId(value = "log_id")
private String log_id;
/**
* 描述
*/
private String description;
/**
* 日志类型
*/
private String log_type;
/**
* 日志类别
*/
private String log_dtl_info;
/**
* 日志级别
*/
private String log_level;
/**
* 方法
*/
private String method;
/**
* 参数
*/
private String params;
/**
* 请求ip
*/
private String request_ip;
/**
* 时间
*/
private Long time;
/**
* 用户名字
*/
private String username;
/**
* 地址
*/
private String address;
/**
* 浏览器
*/
private String browser;
/**
* 返回结果
*/
private String return_result;
/**
* 异常明细
*/
private byte[] exception_detail;
/**
* 创建时间
*/
private String create_time;
public SysInterfaceLog(String logType, Long time) {
this.log_type = logType;
this.time = time;
}
}

View File

@@ -0,0 +1,16 @@
package org.nl.system.service.logging.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.nl.system.service.logging.dao.SysInterfaceLog;
/**
* <p>
* 系统日志表 Mapper 接口
* </p>
*
* @author author
* @since 2024-07-29
*/
public interface SysInterfaceLogMapper extends BaseMapper<SysInterfaceLog> {
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.nl.system.service.logging.dao.mapper.SysInterfaceLogMapper">
</mapper>

View File

@@ -0,0 +1,96 @@
package org.nl.system.service.logging.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.nl.modules.common.utils.StringUtils;
import org.nl.modules.logging.annotation.Log;
import org.nl.system.service.logging.ISysInterfaceLogService;
import org.nl.system.service.logging.dao.SysInterfaceLog;
import org.nl.system.service.logging.dao.SysLog;
import org.nl.system.service.logging.dao.mapper.SysInterfaceLogMapper;
import org.nl.system.service.logging.dao.mapper.SysLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.support.MultipartFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 系统日志表 服务实现类
* </p>
*
* @author author
* @since 2024-07-29
*/
@Service
public class SysInterfaceLogServiceImpl extends ServiceImpl<SysInterfaceLogMapper, SysInterfaceLog> implements ISysInterfaceLogService {
@Override
public void save(String username, String outParam, String browser, String ip, ProceedingJoinPoint joinPoint, SysInterfaceLog logDto) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String[] split = joinPoint.getTarget().getClass().getName().split("\\.");
String className = split[split.length - 1];
assert logDto != null;
logDto.setRequest_ip(ip);
logDto.setAddress(StringUtils.getCityInfo(logDto.getRequest_ip()));
logDto.setMethod(signature.getName());
logDto.setUsername(username);
logDto.setParams(JSONUtil.toJsonStr(filterArgs(joinPoint.getArgs())).replace("\\",""));
logDto.setBrowser(browser);
logDto.setReturn_result(outParam);
logDto.setLog_dtl_info(className);
logDto.setLog_id(IdUtil.getSnowflake(1, 1).nextIdStr());
logDto.setCreate_time(DateUtil.now());
this.save(logDto);
}
private String getParameter(Method method, Object[] args) {
List<Object> argList = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
//将RequestBody注解修饰的参数作为请求参数
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
if (requestBody != null) {
argList.add(args[i]);
}
//将RequestParam注解修饰的参数作为请求参数
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
if (requestParam != null) {
Map<String, Object> map = new HashMap<>();
String key = parameters[i].getName();
if (!StrUtil.isEmpty(requestParam.value())) {
key = requestParam.value();
}
map.put(key, args[i]);
argList.add(map);
}
}
if (argList.size() == 0) {
return "";
}
return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList);
}
private List<Object> filterArgs(Object[] args) {
return Arrays.stream(args).filter(object -> !(object instanceof MultipartFilter)
&& !(object instanceof HttpServletRequest)
&& !(object instanceof HttpServletResponse)
).collect(Collectors.toList());
}
}

View File

@@ -68,7 +68,7 @@ spring:
jobStore:
threadPool:
threadCount: 14
# class: org.nl.system.service.quartz.SimpleThreadPool
# class: org.nl.system.service.quartz.SimpleThreadPool
scheduler-name: quartzScheduler
task:
pool:
@@ -92,6 +92,11 @@ logging:
file:
path: d:\log\lms
config: classpath:logback-spring.xml
include-paths:
- /api/mes/**
- /api/lms/**
- /api/sap/**
- /api/crm/**
# sa-token白名单配置
security:
# 排除路径
@@ -151,7 +156,7 @@ sa-token:
mybatis-plus:
configuration:
map-underscore-to-camel-case: false
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations:
- classpath:org.nl.**.mapper/*.xml
global-config: