Controller 自动化日志输出

Starter库

1.定义注解

复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TraceLog {
    /**
     * 日志类型
     *
     * @return
     */
    String type() default "";
}

2.定义捕获日志接口方法

复制代码
public interface ITraceLogProcess {

    void afterThrowing(JoinPoint pjp, Throwable ex, Long beforeTime);

    void afterReturning(JoinPoint pjp, Object result, Long beforeTime);

    void before(JoinPoint pjp);
}

3.定义捕获日志方法实现

复制代码
@Slf4j
public class TraceLogProcess implements ITraceLogProcess {
    private static String UNKNOWN_IP = "unknown";

    private static String X_FORWARDED_FOR = "x-forwarded-for";

    @Override
    public void afterThrowing(JoinPoint pjp, Throwable ex, Long beforeTime) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        TraceLog traceLog = method.getAnnotation(TraceLog.class);
        Integer errorCode = ResultCode.UNKNOWN_CODE.getCode();
        String errorMsg = ResultCode.UNKNOWN_CODE.getDesc();
        if (ex instanceof ApiException) {
            errorCode = ((ApiException) ex).getResultCode();
            errorMsg = ex.getMessage();
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        log.info("[Tracelog failed] Call interface[{}] from IP[{}] return error," +
                        "URL:[{}], method name:[{}]," +
                        "method type:[{}], expend time(ms):[{}]," +
                        "input parameter:[{}]," +
                        "error code:[{}], error message:[{}]",
                traceLog != null ? traceLog.type() : "", getIpAddr(request),
                request.getRequestURL().toString(), signature.getName(),
                request.getMethod(), System.currentTimeMillis() - beforeTime,
                pjp.getArgs(), errorCode, errorMsg);
    }

    @Override
    public void afterReturning(JoinPoint pjp, Object result, Long beforeTime) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        TraceLog traceLog = method.getAnnotation(TraceLog.class);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        log.info("[Tracelog success]Call interface[{}] from IP[{}]," +
                        "URL:[{}], method name:[{}]," +
                        "method type:[{}], expend time(ms):[{}]," +
                        "input parameter:[{}]," +
                        "result:[{}]",
                traceLog != null ? traceLog.type() : "", getIpAddr(request),
                request.getRequestURL().toString(), signature.getName(),
                request.getMethod(), System.currentTimeMillis() - beforeTime,
                pjp.getArgs(), JSONObject.toJSONString(result));
    }

    @Override
    public void before(JoinPoint pjp) {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        TraceLog traceLog = method.getAnnotation(TraceLog.class);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        log.info("[Tracelog begin]Call interface[{}] from IP[{}]," +
                        "URL:[{}], method name:[{}]," +
                        "method type:[{}], input parameter:[{}]",
                traceLog != null ? traceLog.type() : "", getIpAddr(request),
                request.getRequestURL().toString(), signature.getName(),
                request.getMethod(), pjp.getArgs());
    }

    private String getIpAddr(HttpServletRequest request) {
        //获取代理服务器IP地址
        String proxyIp = request.getHeader(X_FORWARDED_FOR);
        //如果存在代理服务器IP地址,则从中提取客户端真实IP地址
        if (proxyIp != null && proxyIp.length() != 0) {
            String[] ips = proxyIp.split(",");
            for (String ip : ips) {
                if (!UNKNOWN_IP.equalsIgnoreCase(ip)) {
                    return ip.trim();
                }
            }
        }
        //如果不存在代理服务器IP地址,则直接获取远程IP地址
        return request.getRemoteAddr();
    }
}

4.定义日志捕获切面

复制代码
@Slf4j
@Aspect
public class TraceLogAspect {
    @Resource(name = "traceLogProcess")
    ITraceLogProcess traceLogProcess;

    private Long beforeTime;

    @AfterThrowing(throwing = "ex", value = "@annotation(uih.st.core.traceLog.TraceLog)")
    public void afterThrowing(JoinPoint pjp, Throwable ex) {
        traceLogProcess.afterThrowing(pjp, ex, beforeTime);
    }

    @AfterReturning(returning = "result", value = "@annotation(uih.st.core.traceLog.TraceLog)")
    public void afterReturning(JoinPoint pjp, Object result) {
        traceLogProcess.afterReturning(pjp, result, beforeTime);

    }

    @Before(value = "@annotation(uih.st.core.traceLog.TraceLog)")
    public void before(JoinPoint pjp) {
        this.beforeTime = System.currentTimeMillis();
        traceLogProcess.before(pjp);
    }
}

5.通过AutoConfiguration实现注入

复制代码
@Configuration
@ConditionalOnWebApplication
public class TraceLogAutoConfiguration {
    @Bean(name = "traceLogProcess")
    @ConditionalOnMissingBean(name = "traceLogProcess")
    public ITraceLogProcess traceLogProcess() {
        return new TraceLogProcess();
    }

    @Bean
    public TraceLogAspect traceLogAspect() {
        return new TraceLogAspect();
    }
}

6.starter文件spring.factories新增类

复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=core.TraceLogAutoConfiguration

应用使用

将上述实现的starter通过依赖引用后:

复制代码
@TraceLog(type = "aaaaaa")
@PostMapping("/test")
public Result<Boolean> test() {
    return Result.success();
}
相关推荐
仍然.2 分钟前
多线程---CAS,JUC组件和线程安全的集合类
java·开发语言
航Hang*3 分钟前
VMware vSphere 云平台运维与管理基础——第5章:VMware vSphere 5.5 高级特性
运维·服务器·开发语言·windows·学习·虚拟化
不懂的浪漫7 分钟前
mqtt-plus 架构解析(五):错误处理与 ErrorAction 聚合策略
java·spring boot·后端·物联网·mqtt·架构
呼啦啦56114 分钟前
C++vector
java·c++·缓存
花千树-01015 分钟前
MCP + Function Calling:让模型自主驱动工具链完成多步推理
java·agent·react·mcp·toolcall·harness·j-langchain
Benszen18 分钟前
Linux容器:轻量级虚拟化革命
java·linux·运维
问简21 分钟前
ubuntu 字体相关问题
运维·服务器·ubuntu
凸头21 分钟前
Lombok 包底层浅析
java
不懂的浪漫23 分钟前
mqtt-plus 架构解析(三):Payload 序列化与反序列化,为什么要拆成两条链
java·spring boot·物联网·mqtt·架构
卷福同学29 分钟前
去掉手机APP开屏广告,李跳跳2.2下载使用
java·后端·算法