AOP+注解实现通用日志记录

0,前言

在项目开发中,日志记录是一件很重要的事情,下面介绍使用AOP,自定义注解来实现记录项目日志。

最终要实现的效果是,在Controller方法上,加上自定义注解,就在数据库自动记录当前操作。

示例:在UserController 的addUser方法加自定义注解@AutoLog

 

 数据库系统日志表记录此次操作:

 

下面开始实现该功能

1,表

 SQL:

CREATE TABLE `sys_log`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `log_type` tinyint(4) NULL DEFAULT NULL COMMENT '日志类型(1登录日志,2操作日志)',
  `log_content` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '日志内容',
  `operate_type` tinyint(2) NULL DEFAULT NULL COMMENT '操作类型(1-查询;2-添加;3-更新;4-删除;5-导入;6-导出)',
  `userid` int(32) NULL DEFAULT NULL COMMENT '操作用户账号',
  `username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作用户名称',
  `ip` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'IP',
  `method` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求java方法',
  `request_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求路径',
  `request_param` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '请求参数json',
  `request_type` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求类型',
  `cost_time` bigint(20) NULL DEFAULT NULL COMMENT '耗时',
  `create_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '创建人',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '更新人',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `index_table_userid`(`userid`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统日志表' ROW_FORMAT = Dynamic;

2,代码

用mybatis plus生成Entity、Mapper、Service

自定义注解

/**
 * 系统日志
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AutoLog {
    /**
     *日志内容
     * @return
     */
    String value() default "";

    /**
     * 日志类型
     *
     * @return ;1:登录日志;2:操作日志
     */
    int logType() default CrcConstants.LOG_TYPE_2;


    /**
     * 操作日志类型
     *
     * @return (1查询,2添加,3修改,4删除)
     */
    int operateType() default 0;
}

常量类:

/**
 * Created by: lhy on 2019-06-18
 * 常量
 **/
public class CrcConstants {


    /**
     * 系统日志类型: 登录
     */
    public static final int LOG_TYPE_1 = 1;

    /**
     * 系统日志类型: 操作
     */
    public static final int LOG_TYPE_2 = 2;



    /**
     * 操作日志类型: 查询
     */
    public static final int OPERATE_TYPE_1 = 1;

    /**
     * 操作日志类型: 添加
     */
    public static final int OPERATE_TYPE_2 = 2;

    /**
     * 操作日志类型: 更新
     */
    public static final int OPERATE_TYPE_3 = 3;

    /**
     * 操作日志类型: 删除
     */
    public static final int OPERATE_TYPE_4 = 4;

    /**
     * 操作日志类型: 倒入
     */
    public static final int OPERATE_TYPE_5 = 5;

    /**
     * 操作日志类型: 导出
     */
    public static final int OPERATE_TYPE_6 = 6;
}

 切面类:

import com.alibaba.fastjson.JSONObject;
import com.farinfo.common.utils.IpUtils;
import com.farinfo.crc.config.AutoLog;
import com.farinfo.crc.domain.CrcUser;
import com.farinfo.crc.domain.SysLog;
import com.farinfo.crc.service.CrcUserService;
import com.farinfo.crc.service.SysLogService;
import com.farinfo.crc.utils.CrcConstants;
import com.farinfo.crc.utils.SpringContextUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * Created by: lhy on 2020-03-27
 **/
@Aspect
@Component
public class AutoLogAspect {

    @Autowired
    private SysLogService logService;

    @Autowired
    private CrcUserService userService;


    //切点
    @Pointcut("@annotation(com.farinfo.crc.config.AutoLog)")
    public void logPointCut() {

    }

    /**
     * 环绕增强
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //保存日志
        saveSmsLog(point, time);
        return result;
    }




    private void saveSmsLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        SysLog sysLog = new SysLog();
        AutoLog syslog = method.getAnnotation(AutoLog.class);
        if(syslog != null){
            //注解上的描述,操作日志内容
            sysLog.setLogContent(syslog.value());
            sysLog.setLogType(syslog.logType());
        }

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");


        //设置操作类型
        if (sysLog.getLogType() == CrcConstants.LOG_TYPE_2) {
            sysLog.setOperateType(getOperateType(methodName, syslog.operateType()));
        }

        //请求的参数
        Object[] args = joinPoint.getArgs();
        try{
            String params = JSONObject.toJSONString(args);
            sysLog.setRequestParam(params);
        }catch (Exception e){

        }

        //获取request
        HttpServletRequest request = SpringContextUtil.getHttpServletRequest();
        //设置IP地址
        sysLog.setIp(IpUtils.getIpAddr(request));

        //获取登录用户信息,看你用的什么安全框架了,可以从安全上下文获取
        int userId = 35;
        CrcUser user = userService.selectById(userId);
        if(user != null){
            sysLog.setUsername(user.getLoginName());
            sysLog.setUserid(userId);
        }

        //耗时
        sysLog.setCostTime(time);
        sysLog.setCreateTime(new Date());
        //保存系统日志
        logService.insert(sysLog);
    }
    /**
     * 获取操作类型
     */
    private int getOperateType(String methodName,int operateType) {
        if (operateType > 0) {
            return operateType;
        }
        if (methodName.startsWith("list")) {
            return CrcConstants.OPERATE_TYPE_1;
        }
        if (methodName.startsWith("add")) {
            return CrcConstants.OPERATE_TYPE_2;
        }
        if (methodName.startsWith("edit")) {
            return CrcConstants.OPERATE_TYPE_3;
        }
        if (methodName.startsWith("delete")) {
            return CrcConstants.OPERATE_TYPE_4;
        }
        if (methodName.startsWith("import")) {
            return CrcConstants.OPERATE_TYPE_5;
        }
        if (methodName.startsWith("export")) {
            return CrcConstants.OPERATE_TYPE_6;
        }
        return CrcConstants.OPERATE_TYPE_1;
    }
}

实验:

@RequestMapping("/testIdem")
@RestController
public class TestIdemController {

    @Autowired
    private CrcUserService userService;

    @AutoLog(value = "添加用户", operateType = CrcConstants.OPERATE_TYPE_2)
    @PostMapping("addUser")
    public String addUser(@RequestBody CrcUser user){
        userService.insert(user);
        return "OK";
    }

}

 User表:

 sys_log表:

如果想记录详细的日志信息,可以调用logSrvice.addLog() 进行自行添加。

猜你喜欢

转载自www.cnblogs.com/lihaoyang/p/12581847.html