spring 切片操作日志实现

spring 切片操作日志实现

  • 依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    
  • 代码实现

    package com.chaoyang.model;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    
    @Data
    @EqualsAndHashCode(callSuper=false)
    public class WebLog {
        /**
        * 操作描述
        */
        private String description;
    
        /**
        * 操作用户
        */
        private String username;
    
        /**
        * 消耗时间
        */
        private Integer spendTime;
    
        /**
        * 根路径
        */
        private String basePath;
    
        /**
        * URI
        */
        private String uri;
    
        /**
        * URL
        */
        private String url;
    
        /**
        * 请求类型
        */
        private String method;
    
        /**
        * IP地址
        */
        private String ip;
    
        /**
        * 请求参数
        */
        private Object parameter;
    
        /**
        * 返回结果
        */
        private Object result;
    }
    
    
    package com.chaoyang.aspect;
    
    import cn.hutool.core.util.StrUtil;
    import cn.hutool.core.util.URLUtil;
    import com.alibaba.fastjson.JSON;
    import com.chaoyang.model.WebLog;
    import io.swagger.annotations.ApiOperation;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
    import org.springframework.core.annotation.Order;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    
    
    @Slf4j
    @Component
    @Aspect
    @Order(1)
    public class WebLogAspect {
    
        /**
        * 定义一个切入点
        */
        @Pointcut("execution(* com.chaoyang.controller.*.*(..))")
        public void webLog(){
    
        }
        /**
        * 环绕通知
        */
        @Around("webLog()")
        public Object recordWebLog(ProceedingJoinPoint joinPoint) throws Throwable {
            Object result = null;
            WebLog webLog = new WebLog();
            //接口请求时间
            long start = System.currentTimeMillis();
            //这个地方将全局的异常抛出去不然web层的全局异常就捕获不了了
            result = joinPoint.proceed(joinPoint.getArgs());
            //结束时间
            long endTime = System.currentTimeMillis();
            webLog.setSpendTime((int) (start - endTime) / 1000);
            //获取当前请求的request对象
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            webLog.setUri(request.getRequestURI());
            String url = request.getRequestURL().toString();
            webLog.setUrl(url);
            webLog.setBasePath(StrUtil.removeSuffix(url, URLUtil.url(url).getPath()));
            //获取安全的上下文
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            webLog.setUsername(authentication == null ? "匿名用户" : authentication.getPrincipal().toString());
            webLog.setIp(request.getRemoteAddr()); //todo
            //方法签名
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            //获取类的名称
            String name = joinPoint.getTarget().getClass().getName();
            ApiOperation annotation = method.getAnnotation(ApiOperation.class);
            webLog.setDescription(annotation == null ? "no desc" : annotation.value());
            webLog.setMethod(name + "." + method.getName());
            //这个地方方法参数做成k<->v的形式
            webLog.setParameter(getParam(method, joinPoint.getArgs()));
            webLog.setResult(result);
            log.info(JSON.toJSONString(webLog));
            return result;
        }
    
        private Object getParam(Method method, Object[] args) {
            HashMap<String, Object> map = new HashMap<>();
            LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
            //方法的新参名称
            String[] parameterNames = discoverer.getParameterNames(method);
            if (parameterNames != null && parameterNames.length > 0) {
                for (int i = 0; i < parameterNames.length; i++) {
                    map.put(parameterNames[i], args[i]);
                }
            }
            return map;
        }
    }
    
    
    
posted @ 2025-08-07 09:36  巫小诗  阅读(12)  评论(0)    收藏  举报