Retrofit 自定义注解 实现可选择性的打印接口日志

news2024/9/28 7:22:41

序言

有时候我们需要打印okhttp的日志,但是现在的日志拦截器,不能做到接口级别的日志输出控制。要么就是全部打印。这样很影响调试效率。所以我在这块做了一些探索。

使用效果

普通输出

只需要在要打印日志的接口上添加 @PrintLog 注解就可以打印,没有添加的接口不会打印
在这里插入图片描述

打印出来的日志

tag通过初始化的时候指定

httpClient.addInterceptor(new LoginControlInterceptor("ok_http_log"));

在这里插入图片描述

支持自定义tag

参数定义

在这里插入图片描述

输出效果在这里插入图片描述

使用

日志打印功能基于下面的库实现,需要添加下面的库为支撑。


    implementation 'com.github.fengzhizi715.okhttp-logging-interceptor:core:v1.1.4'

下面三个自定义的类

AndroidLogProxy

package com.trs.library.rx2.http.http_log;

import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import cn.netdiscovery.http.interceptor.log.LogProxy;


/**
 * <pre>
 * Created by zhuguohui
 * Date: 2024/8/8
 * Time: 10:34
 * Desc:
 * </pre>
 */
public class AndroidLogProxy implements LogProxy {
    private String tempTag;

    @Override
    public void d(@NonNull String s, @NonNull String s1) {

        Log.d(getTag(s), s1);
    }
    private String getTag(String tag){
        if(!TextUtils.isEmpty(tempTag)){
            return tempTag;
        }else{
            return tag;
        }
    }

    @Override
    public void e(@NonNull String s, @NonNull String s1) {
        Log.e(getTag(s), s1);
    }

    @Override
    public void w(@NonNull String s, @NonNull String s1) {
        Log.w(getTag(s), s1);
    }

    @Override
    public void i(@NonNull String s, @NonNull String s1) {
        Log.i(getTag(s), s1);
    }

    public void setTempTag(String tempTag) {
        this.tempTag = tempTag;
    }


}


LoginControlInterceptor

package com.trs.library.rx2.http.http_log;

import com.trs.library.BuildConfig;

import java.io.IOException;
import java.lang.annotation.Annotation;

import cn.netdiscovery.http.interceptor.LoggingInterceptor;
import cn.netdiscovery.http.interceptor.log.LogManager;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Invocation;

/**
 * <pre>
 * Created by zhuguohui
 * Date: 2024/8/8
 * Time: 11:33
 * Desc:控制是否输出日志的拦截器
 * </pre>
 */
public class LoginControlInterceptor implements Interceptor {
    private final AndroidLogProxy androidLogProxy;
    Interceptor logInterceptor;

    public LoginControlInterceptor(String tag) {
        androidLogProxy = new AndroidLogProxy();
        LogManager.INSTANCE.logProxy(androidLogProxy);
        logInterceptor = new LoggingInterceptor.Builder()
                .loggable(BuildConfig.DEBUG) // TODO: 发布到生产环境需要改成false
                .request()
                .requestTag(tag)
                .response()
                .responseTag(tag)
                .build();
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Invocation invocation = request.tag(Invocation.class);
        Annotation[] declaredAnnotations = invocation.method().getDeclaredAnnotations();
        boolean printLog = false;
        String tempTag = null;
        for (Annotation ano : declaredAnnotations) {
            if (ano.annotationType() == PrintLog.class) {
                printLog = true;
                tempTag = ((PrintLog) ano).value();
            }
        }
        if (printLog) {
            //需要打印日志
            if (logInterceptor != null) {
                androidLogProxy.setTempTag(tempTag);
                Response response = logInterceptor.intercept(chain);
                androidLogProxy.setTempTag(null);
                return response;
            }
        }
        return chain.proceed(chain.request());
    }
}


注解 PrintLog

package com.trs.library.rx2.http.http_log;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

/**
 * <pre>
 * Created by zhuguohui
 * Date: 2024/8/8
 * Time: 16:20
 * Desc:用于打印日志
 * </pre>
 */
@Target(METHOD)
@Retention(RUNTIME)
public @interface PrintLog {

    String value() default "";
}



使用

httpClient.addInterceptor(new LoginControlInterceptor("ok_http_log"));

难点

难点主要是怎么在拦截器中获取自定义注解,看来Retrofit的源码,它把被反射的方法保存在。tag的Invocation中。通过下面的方法获取。

        Request request = chain.request();
        Invocation invocation = request.tag(Invocation.class);
        Annotation[] declaredAnnotations = invocation.method().getDeclaredAnnotations();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1992314.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

奥运足球背后的中国小公司

有一家中国的小公司叫做顶碁运动&#xff0c;居然打败了耐克和阿迪达斯这样的巨头&#xff0c;成功地成为了现在巴黎奥运会的足球供应商。 顶碁运动研发的足球&#xff0c;最大的优点就是能够在一秒钟之内精准地识别500次。因为他们在足球的内胆里面装置了芯片和传感器&#xf…

【Linux】:进程控制1(创建、终止、等待)

目录 1.进程创建 2.进程终止&#xff08;退出&#xff09; 2.1 什么是进程终止 2.2 进程退出的场景&#xff08;原因&#xff09; 2.3 进程退出码 2.4 错误码errno 2.5 进程常见的退出方法 正常终止 从main函数返回 调用库函数exit 系统接口_exit 3.进程等待 3.1 …

[qt] 多线程应用02

源码: 点击此处 一 UI 1.1 效果 1.2 代码 首先定义一系列的控件和按钮&#xff0c;用来显示Tcp连接数据信息。 QLabel *m_serverNameLabel;QLineEdit *m_serverLineEdit;QLabel *m_portLabel;QLineEdit *m_portLineEdit;QDateTimeEdit *m_d…

【书生大模型实战营第三期】基础岛 第3关 浦语提示词工程实践

欢迎大家参与第三期书生大模型实战营&#xff01;&#xff01;&#xff01; 1. 基础任务 背景问题&#xff1a;近期相关研究发现&#xff0c;LLM 在对比浮点数字时表现不佳&#xff0c;经验证&#xff0c;internlm2-chat-1.8b&#xff08;internlm2-chat-7b&#xff09;也存在这…

数据结构——排序(2):选择排序+交换排序

目录 一、选择排序 &#xff08;1&#xff09;直接选择排序 ①思路 ②过程图示 ③代码实现 ④代码解释 ⑤优化 1.代码实现 2.过程图示 3.代码解释 4.注意 ⑥直接选择排序的复杂度 &#xff08;2&#xff09;堆排序 ①注意 ②代码实现 二、交换排序 &#xff08…

一键生成!AI绘画、视频制作与写作神助攻

市面上有各种各样的AI助手&#xff0c;它们覆盖了文字处理、图像编辑、视频制作到语音识别等众多领域。这些工具设计得既实用又友好&#xff0c;几乎每个人都能找到适合自己的那一款。 1. 文字处理助手 文本生成&#xff1a;帮你快速创作文章、博客等内容。 内容优化&#xff…

操作ArkTS页面跳转及路由相关心得

本文为JS老狗原创。 当前端不得不关注的点&#xff1a;路由&#xff0c;今天聊一聊鸿蒙相关的一点心得。 总体上套路不意外&#xff0c;基本就是&#xff08;尤其是Web&#xff09;前端那些事&#xff1a;维护路由表、跳转带参数、历史堆栈操作&#xff0c;等等。 历史原因&…

越秀·星汇城|大城好生活

建筑&#xff0c;是美好生活的载体。而户型则是住宅的灵魂&#xff0c;一处好的居所&#xff0c;承载理想生活盛放。 细腻的美好藏在生活各个角落&#xff0c;星汇城以24小时贯穿的细节享受&#xff0c;重新定义幸福该有的舒适。诉说生活的达观&#xff0c;臻藏岁月静好。 8:…

windows系统获取网卡信息

在抓包或者使用socket&#xff0c;或者监听端口时&#xff0c;如果使用的是pcap4j类库&#xff0c;就会用到网卡信息&#xff0c;那么怎么查看本机的网卡信息呢&#xff0c;Linux的比较方便&#xff0c;直接通过ifconfig命令就能看到&#xff0c; windows的比较麻烦一点&#x…

【名单】山东省2024年度第一批DCMM贯标试点企业名单

​各市工业和信息化局&#xff1a; 为深入贯彻全省工业经济头号工程推进会议有关部署&#xff0c;全面落实《关于加快数字经济高质量发展的意见》《2024年“促进经济巩固向好、加快绿色低碳高质量发展”政策清单&#xff08;第一批&#xff09;》等文件要求&#xff0c;充分发…

从根儿上学习spring 十 之run方法启动第四段(4)

我们接着上一节已经准备开始分析AbstractAutowireCapableBeanFactory#doCreateBean方法&#xff0c;该方法是spring真正开始创建bean实例并初始化bean的入口方法&#xff0c;属于核心逻辑&#xff0c;所以我们新开一节开始分析。 图12 图12-530到536行 这几行的主要就是创建b…

先天亏钱圣体!谢瑜、陈梦、全红婵夺冠后,我看到了最残酷的社交真相——早读(逆天打工人爬取热门微信文章解读)

我怎么寻思这是普通事故 引言Python 代码第一篇 洞见 谢瑜、陈梦、全红婵夺冠后&#xff0c;我看到了最残酷的社交真相第二篇 亏麻了结尾 没想到是辆切糕车 引言 昨天文章的数据不错呀 200 的阅读 20的收藏 10:1已经是很高的比例了 再来干货吧 以后大家要是做视频 心中看到这…

Spring Cloud微服务项目聚合Swagger文档

在微服务架构中&#xff0c;每个服务通常都有自己独立的 API 文档。为了方便管理和查看所有服务的接口文档&#xff0c;我们需要将这些文档进行聚合。Spring Cloud 与 Swagger 的结合可以帮助我们实现这一目标。本文将介绍如何在 Spring Cloud 微服务项目中聚合 Swagger 文档&a…

72 成员方法、类方法、静态方法、抽象方法

在面向对象程序设计中&#xff0c;函数和方法这两个概念是有本质区别的。方法一般指与特定实例绑定的函数&#xff0c;通过对象调用方法时&#xff0c;对象本身将被作为第一个参数自动传递过去&#xff0c;普通函数并不具备这个特点。 class Demo:passt Demo()def test(self,…

html+css网页设计公司网站模版3个页面 无js 静态页面

htmlcss网页设计公司网站模版3个页面 无js 静态页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源…

推送给女朋友让她自己学习打光去(Stable Diffusion进阶篇:Imposing Consistent Light)

大家好我是极客菌&#xff01;&#xff01;&#xff01; 对于学过stable diffusion的小伙伴来说&#xff0c;forge UI和Comfy UI会更加熟悉一些。在IC-Light发布后&#xff0c;Openpose editor的开发者将其制作成了一个Forge UI上的插件。 **https://github.com/huchenlei/sd-…

国内有哪些可以交易上证50etf期权的平台?

随着期权交易的普及&#xff0c;越来越多的投资者开始关注期权交易app平台。期权开通方式有券商和期权分仓平台两种&#xff0c;目前期权交易费用是7元左右一张&#xff0c;期权佣金是可以根据券商的证券范围进行调整的&#xff0c;下文为大家科普国内有哪些可以交易上证50etf期…

接口入门(企业常见使用,一分钟搞定版)

目录 1、接口的定义 定义位置 接口内容 2、接口的使用 正常实现接口 接口当做函数参数 匿名实现接口 3、OPPO便签接口具体分析 总结一下&#xff1a; 1、接口的定义 定义位置 可以写在类中&#xff0c;但注意现在接口名字是 类名.接口名 可以单独写在一个文件 接口内…

Linux系统使用Docker安装RStudio服务并实现任意浏览器远程访问

文章目录 前言1. 安装RStudio Server2. 本地访问3. Linux 安装cpolar4. 配置RStudio server公网访问地址5. 公网远程访问RStudio6. 固定RStudio公网地址 前言 RStudio Server 使你能够在 Linux 服务器上运行你所熟悉和喜爱的 RStudio IDE&#xff0c;并通过 Web 浏览器进行访问…

OpenCV图像滤波(8)getGaborKernel()函数的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数返回 Gabor 滤波器系数。 Gabor 滤波器在图像处理中非常有用&#xff0c;特别是在纹理分析、特征提取和边缘检测等领域。 函数原型 Mat c…