spring aop应用---记录日志

本文介绍了如何在SpringBoot项目中使用AOP实现操作日志的自动捕获和记录,包括使用注解定义操作描述、模块和类型,以及在方法执行前后收集相关信息并生成详细日志。
摘要由CSDN通过智能技术生成

引入依赖


		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

编写注解


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperLog {

    String operModel() default ""; //操作模块

    String operType() default "";  //操作类型

    String operDesc() default "";  //操作说明
}

解析注解


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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 org.springframework.web.multipart.MultipartFile;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.*;

@Aspect
@Component
@Slf4j
public class OperLogAspect {

    @Autowired
    private ObjectMapper objectMapper;

    private ThreadLocal<Date> startTime = new ThreadLocal<>();

//    @Pointcut("@annotation(com.example.mybatisplusdemo.logscan.OperLog)")
    @Pointcut("execution(* com.example.mybatisplusdemo.controller.*.*(..))")
    public void pointcut(){
    }

    @Before("pointcut()")
    public void doBefore(JoinPoint joinPoint){
        startTime.set(new Date());
    }

    @AfterReturning(pointcut = "pointcut()",returning = "rvt")
    public void doAfterReturning(JoinPoint joinPoint, Object rvt) throws Exception {
        HttpServletRequest request = getRequest();
        String uri = request.getRequestURI();
        Method method = getMethod(joinPoint);
        OperLog operLog = method.getAnnotation(OperLog.class);
        if(operLog != null){
            String operDesc = operLog.operDesc();
            String operModel = operLog.operModel();
            String operType = operLog.operType();
            log.info("operDesc : {}",operDesc);
            log.info("operModel : {}",operModel);
            log.info("operType : {}",operType);
        }
        // 获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        // 获取请求的方法名
        String methodName = method.getName();
        // 请求的参数
        Map<String, String> reqMap = converMap(request.getParameterMap());
        String reqStr = objectMapper.writeValueAsString(reqMap);
        String responseResult = objectMapper.writeValueAsString(rvt);
        log.info("uri : {}",uri);
        log.info("className : {}",className);
        log.info("methodName : {}",methodName);
        log.info("reqStr : {}",reqStr);
        log.info("responseResult : {}",responseResult);
        log.info("startTime : {}",startTime.get());
        log.info("endTime : {}",new Date());
        Object[] args = joinPoint.getArgs();
        log.info("args : {}", args);
        startTime.remove();
        String ip = getClientIp(request);
        log.info("ip : {}",ip);


        /*LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        if (args != null && paramNames != null) {
            StringBuilder params = new StringBuilder();
            handleParams(params, args, Arrays.asList(paramNames));
            log.info("参数 : {}",params.toString());
        }*/

    }

    private Method getMethod(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        return signature.getMethod();
    }

    private HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes.getRequest();
    }

    public Map<String,String> converMap(Map<String, String[]> paramMap){
        Map<String,String> reMap = new HashMap<>();
        for (String key : paramMap.keySet()) {
            reMap.put(key,paramMap.get(key)[0]);
        }
        return reMap;
    }


    private StringBuilder handleParams(StringBuilder params, Object[] args, List paramNames) throws JsonProcessingException {
        for(int i = 0; i < args.length; ++i) {
            if (args[i] instanceof Map) {
                Set set = ((Map)args[i]).keySet();
                List list = new ArrayList();
                List paramList = new ArrayList();
                Iterator var8 = set.iterator();

                while(var8.hasNext()) {
                    Object key = var8.next();
                    list.add(((Map)args[i]).get(key));
                    paramList.add(key);
                }

                return this.handleParams(params, list.toArray(), paramList);
            }

            if (args[i] instanceof Serializable) {
                Class aClass = args[i].getClass();

                try {
                    aClass.getDeclaredMethod("toString", null);
                    params.append("  ").append(paramNames.get(i)).append(": ").append(this.objectMapper.writeValueAsString(args[i]));
                } catch (NoSuchMethodException var10) {
                    params.append("  ").append(paramNames.get(i)).append(": ").append(this.objectMapper.writeValueAsString(args[i].toString()));
                }
            } else if (args[i] instanceof MultipartFile) {
                MultipartFile file = (MultipartFile)args[i];
                params.append("  ").append(paramNames.get(i)).append(": ").append(file.getName());
            } else {
                params.append("  ").append(paramNames.get(i)).append(": ").append(args[i]);
            }
        }

        return params;
    }

    public String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknow".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 转换异常信息为字符串
     *
     * @param e
     */
    public String stackTraceToString(Exception e) {
        String exceptionName = e.getClass().getName();
        String exceptionMessage = e.getMessage();
        StackTraceElement[] elements = e.getStackTrace();
        StringBuffer strbuff = new StringBuffer();
        for (StackTraceElement stet : elements) {
            strbuff.append(stet + "\n");
        }
        String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
        return message;
    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值