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() 進行自行添加。
歡迎關注個人公眾號一起交流學習:

