使用Spring aop 将所有请求消息存到数据库日志表里

使用的是AOP的环绕通知注解@Around实现

 

1、首先建好表和实体(此处只展示实体类):

/**
 * <p>
 * 请求日志记录
 * </p>
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class RequestLog implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * bo
     */
    @TableId(value = "BO", type = IdType.AUTO)
    private Integer bo;

    /**
     * 请求url
     */
    @TableField("URL")
    private String url;

    /**
     * ip
     */
    @TableField("IP")
    private String ip;

    /**
     * 请求方式
     */
    @TableField("REQUEST_TYPE")
    private String requestType;

    /**
     * 请求类方法
     */
    @TableField("METHOD_NAME")
    private String methodName;

    /**
     * 请求参数
     */
    @TableField("REQUEST_PARAM")
    private String requestParam;

    /**
     * 响应参数
     */
    @TableField("RESPONSE_PARAM")
    private String responseParam;

    /**
     * 耗时(毫秒)
     */
    @TableField("ELAPSED_TIME")
    private Long elapsedTime;

    /**
     * 模块名
     */
    @TableField("MODULE_NAME")
    private String moduleName;

    /**
     * 创建人
     */
    @TableField("CREATE_USER")
    private String createUser;

    /**

     * 创建时间
     */
    @TableField("CREATE_DATE")
    private Date createDate;


}

 

2、使用环绕通知和request 获取相关信息存储(其中添加了配置文件内的参数控制日志记录是否打开)

/**
 * @description: 使用AOP保存所有请求信息
 * @author: yuanguonan
 * @date: 2021/8/17 10:02
 */
@Aspect
@Component
public class RequestAopLogConfig {

    @Value("${request.log.isOpen}")
    private boolean isOpen;

    @Value("${request.log.moduleName}")
    private String moduleName;

    @Autowired
    private RequestLogService requestLogService;

    //切点(所有请求)
    @Pointcut("execution(public * com.itl.mes.*.provider.controller..*.*(..))")
    private void controllerAspect() {
    }

    @Around("controllerAspect()")
    public Object process(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //开始时间
        long startTime = new Date().getTime();
        //响应结果
        Object result = joinPoint.proceed();
        //结束时间
        long endTime = new Date().getTime();
        //是否开启日志记录
        if (isOpen) {
            RequestLog requestLog = new RequestLog();
            //模块名称
            requestLog.setModuleName(moduleName);
            //IP
            requestLog.setIp(getRemoteHost(request));
            //全路径
            requestLog.setUrl(request.getRequestURL().toString());
            //请求参数
            requestLog.setRequestParam(postHandle(filterParamList(joinPoint)));
            //响应参数
            requestLog.setResponseParam(postHandle(result));
            //请求类型
            requestLog.setRequestType(request.getMethod());
            //类和方法名称
            requestLog.setMethodName(joinPoint.getTarget().getClass().getSimpleName() + "." + joinPoint.getSignature().getName());
            //耗时
            requestLog.setElapsedTime(endTime - startTime);
            //创建人
            requestLog.setCreateUser(UserUtils.getCurrentUser() != null ? UserUtils.getCurrentUser().getUserName() : "testAdmin");
            requestLogService.save(requestLog);
        }
        return result;
    }

    /**
     * 获取目标主机的ip
     *
     * @param request
     * @return
     */
    private String getRemoteHost(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

    /**
     * 返回数据
     *
     * @param retVal
     * @return
     */
    private String postHandle(Object retVal) {
        if (null == retVal) {
            return "";
        }
        return JSON.toJSONString(retVal);
    }

    /**
     * 过滤参数列表
     *
     * @param joinPoint
     * @return
     */
    private List<Object> filterParamList(ProceedingJoinPoint joinPoint) {
        List<Object> paramsList = new ArrayList<>();
        Object[] arrays = joinPoint.getArgs();
        for (int i = 0; i < arrays.length; i++) {
            if (!(arrays[i] instanceof HttpServletRequest)) {
                paramsList.add(arrays[i]);
            }
        }
        return paramsList;
    }

}

 

3、测试后基本满足需求:

使用Spring aop 将所有请求消息存到数据库日志表里

使用Spring aop 将所有请求消息存到数据库日志表里

上一篇:Oracle高可用的3种数据保护模式


下一篇:SQL(DDL、DML、TCL)