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() 进行自行添加。
欢迎关注个人公众号一起交流学习: