Aop打印日志

74 阅读2分钟
 

import com.alibaba.fastjson.JSON;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Configuration
public class LogAopConfig {

    private LoggerHelper log = LoggerHelper.getLoggerHelper(Constants.ModuleName.RESOURCE_MANAGER, LogAopConfig.class.getSimpleName());
    /**
     * 进入方法时间戳
     */
    private Long startTime;
    /**
     * 方法结束时间戳(计时)
     */
    private Long endTime;

    public LogAopConfig() {
    }

    /**
     * 定义请求日志切入点,其切入点表达式有多种匹配方式,这里是指定路径
     */
    @Pointcut("execution(public * com.ly.traffic.ground.buspass.controller..*.*(..))")
    public void webLogPointcut() {
    }

    /**
     * 前置通知:
     * 1. 在执行目标方法之前执行,比如请求接口之前的登录验证;
     * 2. 在前置通知中设置请求日志信息,如开始时间,请求参数,注解内容等
     *
     * @param joinPoint
     * @throws Throwable
     */
    @Before("webLogPointcut()")
    public void doBefore(JoinPoint joinPoint) {

        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        //打印请求的内容
        startTime = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder("");
        sb.append("请求开始时间:").append(LocalDateTime.now().toString()).append("\r\n");
        sb.append("请求Url : ").append(request.getRequestURL().toString()).append("\r\n");
        sb.append("请求方式 : ").append(request.getMethod()).append("\r\n");
        sb.append("请求ip : ").append(request.getRemoteAddr()).append("\r\n");
        sb.append("请求方法 : ").append(joinPoint.getSignature().getDeclaringTypeName()).append(".").append(joinPoint.getSignature().getName()).append("\r\n");
        String paramter = getString(joinPoint);
        sb.append("请求参数 : ").append(paramter);
        log.infoLog(sb.toString());
    }

    private String getString(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        Object[] arguments  = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                //ServletRequest不能序列化,从入参里排除,否则报异常:java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                //ServletResponse不能序列化 从入参里排除,否则报异常:java.lang.IllegalStateException: getOutputStream() has already been called for this response
                continue;
            }
            arguments[i] = args[i];
        }
        String paramter = "";
        if (arguments != null) {
            try {
                paramter = JSON.toJSONString(arguments);
            } catch (Exception e) {
                paramter = arguments.toString();
            }
        }
        return paramter;
    }

    /**
     * 返回通知:
     * 1. 在目标方法正常结束之后执行
     * 1. 在返回通知中补充请求日志信息,如返回时间,方法耗时,返回值,并且保存日志信息
     *
     * @param ret
     * @throws Throwable
     */
    @AfterReturning(returning = "ret", pointcut = "webLogPointcut()")
    public void doAfterReturning(Object ret) throws Throwable {
        endTime = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder("");
        sb.append("请求结束时间:").append(LocalDateTime.now()).append("\r\n");
        sb.append("请求耗时 : ").append((endTime - startTime)).append("\r\n");
        sb.append("请求返回 : ").append(JSON.toJSONString(ret));

        log.infoLog(sb.toString());

    }

    /**
     * 异常通知:
     * 1. 在目标方法非正常结束,发生异常或者抛出异常时执行
     * 1. 在异常通知中设置异常信息,并将其保存
     *
     * @param throwable
     */
    @AfterThrowing(value = "webLogPointcut()", throwing = "throwable")
    public void doAfterThrowing(Throwable throwable) {
        // 保存异常日志记录
        StringBuilder sb = new StringBuilder("");
        sb.append("发生异常时间:").append(LocalDateTime.now()).append("\r\n");
        sb.append("抛出异常 : ").append( throwable.getMessage());

        log.infoLog(sb.toString());
    }

}