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();
}
相关推荐
滕州市燕猫虎计算机科技工作室个体工商户10 小时前
Java面试题汇总
java·开发语言
新时代牛马10 小时前
docker run 起不来?从dockerd、containerd 到runc 一条线讲透
运维·docker·容器
TomEval11 小时前
【App 自动化】14 - App 自动化基础与环境
运维·自动化
新时代牛马11 小时前
Linux 防火墙:nftables 与iptables 兼容层
linux·运维·服务器
xhbh66611 小时前
中小企业 Redis 运维,如何安全归档 RDB、AOF 备份文件?
运维·数据库·缓存·数据备份·文件备份·同步备份·号码备份
是逍遥子没错11 小时前
一个斜杠,击穿整座网关:API网关路径前缀绕过认证实战
运维·服务器·web安全·网络安全·渗透测试·系统安全
2301_322414280411 小时前
活力孕康复APP 47737- 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·mysql·微信小程序·idea·微信开发者工具
君顾111 小时前
外卖CPS软件开发实战:从系统架构到部署全流程指南
java·开发语言·外卖
其实防守也摸鱼12 小时前
每天一个知识点——RCE漏洞
运维·服务器·数据库·windows·安全·github·漏洞
努力努力再努力wz12 小时前
【Docker 入门系列】:从 Namespace、CGroup 到 LXC:理解容器运行时、rootfs 与 LXC 实战
运维·docker·容器