Springboot AOP 之系统操作日志注解形式实现

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:35   1073   0

Spring的两大核心是控制反转(Ioc)和面向切面编程(Aop);今天就聊聊,在以往的项目中是如果通过Aop来实现系统日志的,并将重要的记录结果进行入库。

日志实体类:

/**
 * 日志记录类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Alias("logRecord")
public class LogRecord {
    private Long id;// 主键
    private String operator;//操作者
    private String operateDesc;//操作描述
    private Date operateDate;//操作日期
    private String result;//操作结果
    private String remark;//日志备注
}

说明:日志实体对应的xml文件,Dao,Service,ServiceImpl以及Controller这里就不再贴代码了。

日志记录表结构:

CREATE TABLE `logrecord` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `operator` varchar(255) DEFAULT NULL COMMENT '操作人',
  `operateDesc` varchar(255) DEFAULT NULL COMMENT '操作描述',
  `operateDate` datetime DEFAULT NULL COMMENT '操作时间',
  `result` varchar(255) DEFAULT NULL COMMENT '操作结果',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

日志注解:

/**
 * 日志注解
 */
@Target(ElementType.METHOD)//注解使用在方法上
@Retention(RetentionPolicy.RUNTIME)//注解运行有效
public @interface LogAnno {
    String operateDesc();//操作描述
}

提示:日志注解可以使用在Controller或serviceImpl上,这里选择用在serviceImpl上,见下面代码。

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;

    @Override
    public PageInfo queryUserList(Map<String, Object> queryMap,Integer pageSize,Integer pageNum) {
        PageHelper.startPage(pageNum,pageSize);//分页
        List<User> users = userMapper.queryUserList();
        PageInfo pageInfo = new PageInfo(users);
        return pageInfo;
    }

    @Override
    public List<User> queryByCondition(Map<String, Object> map) {
        return userMapper.queryByCondition(map);
    }

    @LogAnno(operateDesc = "添加用户信息")
    @Override
    public Integer insert(User user) {
        return userMapper.insert(user);
    }

    @LogAnno(operateDesc = "更新用户信息")
    @Override
    public Integer update(User user) {
        return userMapper.update(user);
    }

    @LogAnno(operateDesc = "删除用户信息")
    @Override
    public boolean delete(Integer id) {
        return userMapper.delete(id);
    }
}

切面类:

/**
 * 创建切面类
 * 并添加到容器中
 */
@Aspect
@Component
public class LogAopAspect {

    @Autowired
    LogRecordService logRecordService;//注入日志Service

    /**
     * 环绕通知记录日志通过注解匹配到需要增加日志功能的方法
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("@annotation(com.spb.utils.LogAnno)")
    public Object aroundAdvice(ProceedingJoinPoint pjp) throws Throwable{
        //1.方法执行前的处理,相当于前置通知
        //获取方法
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        //获取方法
        Method method = methodSignature.getMethod();
        //获取方法上面的注解
        LogAnno logAnno = method.getAnnotation(LogAnno.class);
        //获取操作描述的属性
        String operateDesc = logAnno.operateDesc();

        ServletRequestAttributes arr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = arr.getRequest().getSession(true);
        User user = (User)session.getAttribute("loginUser");

        //实例化日志记录对象
        LogRecord logRecord = new LogRecord();
        logRecord.setOperateDesc(operateDesc);//操作描述
        if (user != null) {
            logRecord.setOperator(user.getName());//操作人
        }

        Object result = null;

        try {
            //通过代理方法执行
            result = pjp.proceed();
            //2.相当于后置通知
            logRecord.setResult("正常");
        }catch (Exception e){
            logRecord.setResult("失败");
        }finally {
            logRecord.setOperateDate(new Date());//设置日志记录日期
            logRecordService.insert(logRecord);//日志信息入库
        }

        return result;
    }
}

这里仅对用户的添加、修改、删除的方法做了日志注解,运行程序 ,查看数据库日志数据:

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP