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() 進行自行添加。

 

歡迎關注個人公眾號一起交流學習:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM