利用AOP实现全局拦截记录操作日志demo - 简书

一、概述

java开发AOP(动态代理)是个比较常用的一种开发思想,今天以一个拦截请求记录操作日志的Demo分享下AOP的实现

二、分享开始

2.1 结构

image.png

2.2 日志信息记录类

@Data
public class UserOperation  {

    private static final long serialVersionUID = 1L;

    /**
     * 主键ID
     */
    private Long operationLogId;

    /**
     * 用户昵称
     */
    private String nickname;

    /**
     * 用户账号
     */
    private String username;

    /**
     * 操作名称
     */
    private String methodName;

    /**
     * 操作时间
     */
    private Date operationTime;

    /**
     * 请求IP
     */
    private String requestIp;

    /**
     * 请求URL
     */
    private String requestUrl;

    /**
     * 请求参数
     */
    private String requestParam;

    /**
     * 返回结果
     */
    private String responseResult;

    /**
     * 操作结果
     */
    private String resultStatus;

    /**
     * 错误信息
     */
    private String errorInfo;

    /**
     * 模块
     */
    private String model;

    /**
     * 请求开始时间
     */
    private Date requestStartTime;

    /**
     * 请求结束时间
     */
    private Date requestEndTime;

    /**
     * 响应时间
     */
    private Long responseDate;
}

2.3 AOP实现类

@Aspect
@Slf4j
public class LogControllerAop {
    @Value("${spring.application.name}")
    private String model;

    // 拦截所有@RestController
    @Around("@within(org.springframework.web.bind.annotation.RestController)")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("开始捕获用户操作日志");
        UserOperation userOperation = new UserOperation();
        long startTime = 0;
        try {
            // 获取Request对象
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            LoginAppUser loginAppUser = AppUserUtil.getLoginAppUser();
            if (null != loginAppUser) {
                // 操作人
                userOperation.setUsername(StringUtil.getValue(loginAppUser.getUsername(),"内部feign调用"));
                // 操作人账号
                userOperation.setNickname(StringUtil.getValue(loginAppUser.getNickname(),"内部feign调用"));
            }else {
                // 操作人
                userOperation.setUsername("内部feign调用");
                // 操作人账号
                userOperation.setNickname("内部feign调用");
            }
            // 操作名称
            userOperation.setMethodName(joinPoint.getSignature().getName());
            // 操作时间
            Date date = new Date();
            startTime = date.getTime();
            userOperation.setOperationTime(date);
            // 请求开始时间
            userOperation.setRequestStartTime(date);
            // 请求IP
            userOperation.setRequestIp(IPUtil.getRemoteIpAddr(request));
            // URL
            userOperation.setRequestUrl(request.getRequestURI());
            // 模块
            userOperation.setModel(model);
            Object[] args = new Object[0];
            try {
                // 请求参数
                args = joinPoint.getArgs();
                String param = JSON.toJSONString(args);
                userOperation.setRequestParam(param);
            } catch (Exception e) {
                log.error("截取参数异常"+e);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Object proceed =  null;
        try {
            proceed = joinPoint.proceed();
            userOperation.setResultStatus("success");
            return proceed;
        } catch (Exception e) {
            // 堆栈错误信息
            String stackTrace = Arrays.toString(e.getStackTrace());
            // 错误信息
            String message = e.getMessage();
            ConcurrentHashMap<String, String> errorMsg = new ConcurrentHashMap<>();
            errorMsg.put("stackTrace",stackTrace);
            errorMsg.put("message", e.getClass().getName() + ": " + message);
            userOperation.setErrorInfo(JSON.toJSONString(errorMsg));
            userOperation.setResultStatus("error");
            throw e;
        } finally {
            try {
                if (StringUtil.notEmpty(proceed)) {
                    // 返回结果
                    userOperation.setResponseResult(JSON.toJSONString(proceed));
                }
                // 请求结束时间
                Date endDate = new Date();
                userOperation.setRequestEndTime(endDate);
                userOperation.setResponseDate(endDate.getTime() - startTime);
            } catch (Exception e) {
                log.error("获取返回结果异常{}"+e);
            }
            // 异步将操作日志保存
            CompletableFuture.runAsync(() -> {
                try {
                    // 保存日志,具体方法自定义
                    this.save(userOperation);
                } catch (Exception e2) {
                    log.error("用户操作日记记录异常:{}"+e2);
                }
            });
        }
    }

}

2.4 配置类注解

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(LogControllerAop.class)
public class LogAutoConfiguration {

}

2.5 注入类注解

import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(LogAutoConfiguration.class)
public @interface EnableOpLog {

}
说明:在启动类加上该注解就可以注入

原网址: 访问
创建于: 2020-12-10 11:44:26
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论