首页 > 其他 > 详细

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

时间:2019-08-20 14:06:31      阅读:75      评论:0      收藏: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);
    }

 

 

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

原文:https://www.cnblogs.com/hrf521/p/11382353.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!