文档章节

自定义注解使用aop记录操作日志

o
 osc_wws45aot
发布于 2019/08/20 13:30
字数 797
阅读 11
收藏 0

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

1.自定义注解类

/**
 * @version 1.0.0, 2019/5/5
 * @ClassName: OperationLog
 * @Description: 自定义操作日志记录注解类
 * @since uem v0.0.1
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface OperationLog {

    /**
     * 业务的名称,例如:"修改菜单"
     */
    String operateName() default "";

    /**
     * 操作内容
     */
    String operateContent() default "";

    /**
     * 模块名称
     */
    String modelName() default "";

    /**
     * @return 日志自定义字段描述
     */
    Class logDataDic() default LogDataDic.class;
}

2.aop拦截

package com.dtmobile.uem.nhcm.controller.logger;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Title:
 * @Description: 日志记录的拦截器拦截日志注解
 * @param:
 * @return:
 * @throws:
 * @Author: liduo
 */
@Aspect
@Component
@Slf4j
public class LogAop {

    /**
     * 成功标记
     */
    private final int SUCCESS = 0;

    /**
     * 执行失败标记
     */
    private final int FAILED = 1;
    /**
     * 日志执行器
     */
    @Autowired
    private LogExecutor logExecutor;

    /**
     * 日志切点
     * @param operationLog
     */
    @Pointcut(value = "@annotation(operationLog)")
    public void cutService(OperationLog operationLog) {
        // default pointcut
    }

    /**
     * 正常拦截记录日志
     * @param returnObj  返回值
     * @param joinPoint
     * @param operationLog 操作日志属性
     */
    @AfterReturning(pointcut = "cutService(operationLog)", returning = "returnObj")
    public void doAfterReturning(JoinPoint joinPoint, OperationLog operationLog, Object returnObj) {
        String methodName = joinPoint.getSignature().getName();
        //获取拦截方法的参数
        String className = joinPoint.getTarget().getClass().getName();
        Object[] params = joinPoint.getArgs();
        logExecutor.execute(operationLog, SUCCESS);
    }

    /**
     * 异常拦截记录日志
     *
     * @param operationLog 操作日志属性
     * @param joinPoint 拦截点
     * @param ex 异常处理流程
     */
    @AfterThrowing(pointcut = "cutService(operationLog)", throwing = "ex")
    public void doAfterThrowing(JoinPoint joinPoint, OperationLog operationLog, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        //获取拦截方法的参数
        String className = joinPoint.getTarget().getClass().getName();
        Object[] params = joinPoint.getArgs();
        logExecutor.execute(operationLog, FAILED);
    }
}

@AfterThrowing是一种通知类型,可以确保在方法抛出异常时运行一个通知。 以下是@AfterThrowing通知的语法:

语法

@AfterThrowing(pointcut="execution(* com.yiibai.Student.*(..))", throwing= "error")
public void afterThrowingAdvice(JoinPoint jp, Throwable error){
   System.out.println("Method Signature: "  + jp.getSignature());  
   System.out.println("Exception: "+error);  
}

 

在上面的语法示例中 -

  • @AfterReturning - 如果方法返回成功,则将函数标记为在切入点覆盖的方法之前执行的通知。
  • @Pointcut - 将函数标记为切入点
  • @After - 将函数标记为在切入点覆盖的方法之后执行的通知。
  • execution( expression ) - 涵盖应用通知的方法的表达式。
  • throwing - 返回的异常名称
3.使用多线程发送日志消息给日志模块记录日志
/**
 * Copyright 2019 Datang Mobile Co.,Ltd. All rights reserved.
 * DTM PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 * @Title: LogExecutor
 * @package: com.dtmobile.uem.nhcm.logger
 * @author: walker.Hu(hubing)
 * @date: 2019/6/29
 */
package com.dtmobile.uem.nhcm.controller.logger;

import com.dtmobile.uem.commons.business.process.exception.MessageConfig;
import com.dtmobile.uem.commons.business.process.logger.logMng.LogFactory;
import com.dtmobile.uem.commons.business.process.logger.logMng.OperateLog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static org.apache.commons.lang3.StringUtils.EMPTY;

/**
 * @version 1.0.0, 2019/6/29
 * @className: LogExecutor
 * @description: 日志执行器
 */
@Component
@Slf4j
public class LogExecutor {

    /**
     * 默认延迟
     */
    private static final int OPERATE_DELAY_TIME = 10;

    /**
     * OMC.
     */
    private static final String OMC = "OMC";


    @Autowired
    private MessageConfig messageConfig;

    private LogDataMapper logDataMapper;

    /**
     *
     */
    @Autowired
    private LogFactory logFactory;
    /**
     * 异步操作记录日志的线程池
     */
    private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);

    /**
     * 异步记录操作日志
     *
     * @param operationLog
     * @param result
     */
    public void execute(OperationLog operationLog, int result) {
        // 获取当前登录的用户Ip
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String loginUserName = request.getHeader("loginUserName");
        String clientIp = request.getHeader("clientIp");
        executor.schedule(() -> {
            OperateLog operateLog = createLog(operationLog, result, loginUserName, clientIp);
            logFactory.send(operateLog);
        }, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
    }

    /**
     * 封装操作日志
     *
     * @param operationLog 操作注解
     * @param result       日志标记
     * @return 操作日志对象
     */
    private OperateLog createLog(OperationLog operationLog, int result, String loginUserName, String clientIp) {

        OperateLog operateLog = LogFactory.createOperateLog();
        String operateName = operationLog.operateName();
        String operateContent = messageConfig.getMsg(operationLog.operateContent());
        String modelName = operationLog.modelName();
        operateLog.setTerminalType(operateContent);
        operateLog.setClientIp(null == clientIp ? "127.0.0.1" : clientIp);
        operateLog.setOperUser("".equals(loginUserName) ? "no_user_info" : loginUserName);
        operateLog.setStartTime(new Date());
        operateLog.setEndTime(new Date());
        operateLog.setNeType(OMC);
        operateLog.setNeObject(OMC);
        operateLog.setObjectType(OMC);
        operateLog.setOperateObject(OMC);
        operateLog.setModuleName(modelName);
        operateLog.setOperateName(operateName + "|" + operateContent);
        operateLog.setOperateContent(operateContent);
        operateLog.setResult(result);
        operateLog.setExtraInfo(EMPTY);
        return operateLog;
    }
}

4.自定义注解的使用

@ApiOperation(value = "create task")
    @PostMapping()
    @ApiImplicitParams({@ApiImplicitParam(name = "task", value = "task to be created")})
    @OperationLog(operateName = Const.OperateName.CREATE_TASK,operateContent="createTask",modelName=Const.modelName.modelName)
    public void create(@RequestBody Task task) {
        taskService.create(task);
    }

 

 
o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
SpringAOP+注解实现简单的日志管理

     今天在再次深入学习SpringAOP之后想着基于注解的AOP实现日志功能,在面试过程中我们也经常会被问到:假如项目已经上线,如何增加一套日志功能?我们会说使用AOP,AOP也符合开闭原则:...

osc_qthcwpv9
2018/04/08
119
2
自定义注解实现日志记录

本文分享自微信公众号 - pipi蛋(pipidanfuyun)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。...

浮云X
04/09
0
0
springboot aop 自定义注解方式实现完善日志记录(完整源码)

版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接 一:功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能。 主要记录的信息有: 操作人,方法名,参数,运行...

osc_nrpjz96n
2018/09/13
2
0
springboot—spring aop 实现系统操作日志记录存储到数据库

原文:https://www.jianshu.com/p/d0bbdf1974bd 采用方案: 使用spring 的 aop 技术切到自定义注解上,针对不同注解标志进行参数解析,记录日志 缺点是要针对每个不同的注解标志进行分别取注...

osc_e4uven7h
2018/08/31
7
0
Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录

目的: 需要对一些事物的操作进行日志记录,如果在service内进行记录,大量的代码重复,并且维护比较麻烦。所以采用AOP的方式对service进行拦截。使用自定义注解的目的则是判断是否需要记录日...

凯文加内特
2015/05/12
7.5K
2

没有更多内容

加载失败,请刷新页面

加载更多

VB语言基础重要知识点12

我们课程,我们做一些针对于考试的简要讲解。 一、有关考试的几个问题 首先,提问:考试最重要的是什么? 答案其实很简单:得分!!!!! 想要得分,就要做到基本的保存。 保存哪些文件呢?...

刘金玉编程
2019/10/30
0
0
全网最全JAVA、Python电子书!限时领取,过时不候!

给大家整理了最全的入门+进阶书籍!!! 免费领取,无套路! 加微信发送“电子书” 秒通过,秒发资源! 本文分享自微信公众号 - Python进击者(JAVAandPythonJun)。 如有侵权,请联系 supp...

kuls
01/16
0
0
原创356--免费还是付费

最近得有一个星期,被一个录屏软件(record it)烦到了,本来免费版可以无限制录制,只能720p,GIF不支持,高清不支持,没有剪辑功能。 之前调研了好几种,用起来还是这个方便,就一直用了。...

八音弦
04/24
0
0
数字IC技术讨论群,设计和验证、前端和后端,总有你感兴趣的话题。快满了,需要的抓紧加入。

本文分享自微信公众号 - 白山头讲IC(gray_mount)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。...

白山头
04/29
0
0
how to install mongodb in centos7

[root@xtwj88 ~]# cat /etc/yum.repos.d/mongodb-org-4.2.repo [mongodb-org-4.2]name=MongoDB Repositorybaseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86......

qwfys
12分钟前
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部