SpringBoot中使用aop与mybatis实现日志管理

背景

在项目实际运作中,我们经常需要监听用户进行的操作并进行统计,比如调用了哪个接口,发送了什么请求参数,花了多久时间,这些接口操作记录不仅可以帮助我们时刻观察接口的性能,还能当系统发生错误时保留报错信息,以便于问题复现,因此实现接口操作记录的留存是具有必要性的。
但对于开发流程而言,如果为了留存记录而需要对项目代码进行调整甚至大改,难免有些繁琐且得不偿失。于是在本文中,采用了Aop面向切面编程技术来实现接口日志监听,在不侵入业务代码逻辑的前提下实现了接口使用信息的监听与统计。并使用了mybatis将记录存储至数据库中,提高了代码的可复用性。

效果展示

定义范围为controller包下的接口
在这里插入图片描述

当接口被调用时,数据库进行表的自创建并加入数据
在这里插入图片描述

代码复用流程

将代码放入项目文件夹中
在这里插入图片描述

然后在com.example.received.logStore.StoreLogAspect中修改监听包
在这里插入图片描述

实现过程

创建日志信息封装类StoreLog

import lombok.Data;

@Data
public class StoreLog {

//    private String username;
//    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private String startTime;
    private Integer spendTime;
    private String requestUrl;
    private String requestParams;
    private String methodName;
    private Integer resultCode;
    private Object resultInfo;

}

创建切面类StoreLogAspect

@Aspect
@Component
@Order(1)
@Slf4j
public class StoreLogAspect {

    @Autowired
    logService logService;
    long startTime;

    //定义切点表达式,指定通知功能被应用的范围
    @Pointcut("execution(public * com.example.received.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        startTime = System.currentTimeMillis();
    }


    /**value切入点位置
     * returning 自定义的变量,标识目标方法的返回值,自定义变量名必须和通知方法的形参一样
     * 特点:在目标方法之后执行的,能够获取到目标方法的返回值,可以根据这个返回值做不同的处理
     */
    @AfterReturning(value = "webLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {
        log.info("--------");
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - startTime) + "ms");
    }

    //通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为
    //ProceedingJoinPoint切入点可以获取切入点方法上的名字、参数、注解和对象
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable
    {
        //获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //记录请求信息
        StoreLog webLog = new StoreLog();
        Object result = new Object();
        //前面是前置通知,后面是后置通知
        webLog.setResultInfo("");

        try {
            result = joinPoint.proceed();
            Map res = (Map)result;
            webLog.setResultCode((int)res.get("code"));
        } catch (Throwable e) {
            webLog.setResultCode(500);
            webLog.setResultInfo(e.getCause().toString());
        }
        long endTime = System.currentTimeMillis();

        webLog.setMethodName(request.getMethod());

        webLog.setRequestParams(getParameter(joinPoint));

        webLog.setSpendTime((int) (endTime - startTime));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        webLog.setStartTime( dateFormat.format(new Date(startTime)));

        webLog.setRequestUrl(request.getRequestURL().toString());

        log.info(webLog.toString());
        if(!logService.existTable("storeLog"))
            logService.createTable("storeLog");

        if(!request.getMethod().equals("GET") || !webLog.getResultInfo().equals("")|| webLog.getSpendTime()>200)
            logService.insertLog(webLog.getStartTime(), webLog.getSpendTime(), webLog.getRequestUrl(),webLog.getRequestParams(),
                    webLog.getMethodName(), webLog.getResultCode(), webLog.getResultInfo().toString());
        return result;
    }

    private String getParameter(ProceedingJoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Object[] argsName = methodSignature.getParameterNames();
        Object[] args = joinPoint.getArgs();

        String res = "";
        for (int i = 0; i < args.length; i++)
            log.info(String.valueOf(args[i]));
        for (int i = 0; i < argsName.length; i++)
        {
            log.info(String.valueOf(argsName[i]));
            res += String.valueOf(argsName[i]);
            res += ": ";
            if(args[i]!=null){
                res += String.valueOf(args[i]);
            }
            res += "; ";
        }
        return res;
    }
}

将日志记录存入数据库

@Service
public interface logService {
    Boolean insertLog(String startTime, Integer spendTime, String requestUrl,String requestParams,
                      String methodName, Integer resultCode,String resultInfo);

    Boolean existTable(String tableName);

    Boolean createTable(String tableName);
}
@Service
public class logImpl implements logService {
    @Autowired
    logDao dao;
    @Override
    public Boolean insertLog(String startTime, Integer spendTime, String requestUrl,String requestParams,
                             String methodName, Integer resultCode,String resultInfo) {
        return dao.insertBoard(startTime, spendTime, requestUrl,requestParams, methodName, resultCode,resultInfo);
    }

    @Override
    public Boolean existTable(String tableName){
        return dao.existsTable(tableName);
    };

    @Override
    public Boolean createTable(String tableName){
        return dao.createTable(tableName);
    };

}
@Mapper
public interface logDao {
    @Insert("insert into storeLog (startTime,spendTime,requestUrl,requestParams,methodName,resultCode,resultInfo)" +
            " values(#{startTime},#{spendTime},#{requestUrl},#{requestParams},#{methodName},#{resultCode},#{resultInfo})")
    Boolean insertBoard(String startTime, Integer spendTime, String requestUrl,String requestParams,
                        String methodName, Integer resultCode,String resultInfo);

    @Select(" SELECT COUNT(*) as count FROM information_schema.TABLES WHERE table_name = #{tableName}")
    Boolean existsTable(@Param("tableName") String tableName);

    @Update(" DROP TABLE IF EXISTS `${tableName}`;\n" +
            "CREATE TABLE `${tableName}`  (\n" +
            "  `eventId` bigint NOT NULL AUTO_INCREMENT,\n" +
            "  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,\n" +
            "  `startTime` datetime NULL DEFAULT NULL,\n" +
            "  `spendTime` int NULL DEFAULT NULL,\n" +
            "  `requestUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,\n" +
            "  `requestParams` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,\n" +
            "  `methodName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,\n" +
            "  `resultCode` int NULL DEFAULT NULL,\n" +
            "  `resultInfo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,\n" +
            "  PRIMARY KEY (`eventId`) USING BTREE\n" +
            ") ENGINE = InnoDB AUTO_INCREMENT = 82 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;")
    Boolean createTable(@Param("tableName") String tableName);
}

参考链接
https://blog.csdn.net/CSDN2497242041/article/details/122323507?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6-122323507-blog-104041677.pc_relevant_multi_platform_whitelistv1_exp2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6-122323507-blog-104041677.pc_relevant_multi_platform_whitelistv1_exp2&utm_relevant_index=7

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值