10.请求拦截和响应拦截

前言

优秀的设计总是少不了丰富的扩展点, 比如spring可以自动装配, aop扩展, web模块也有拦截器, 甚至对servlet的过滤器都有封装; 再比如netty、doubbo等等都支持在数据流入流出都允许用户自定义扩展点实现定制化处理, 咱们的feign框架也同样如此, 在可以定制化组件的同时, 也允许我们对发起请求之前和接受请求之后根据扩展点实现个性化的处理。

前景回顾

  1. SynchronousMethodHandler#invoke方法中, 会先用参数填充模板得到有完整请求数据的载体RequestTemplate, 然后执行请求拦截器, 拦截器执行完成之后, 再讲目标请求地址设置给RequestTemplate, 最后构建客户端参数Request
  2. 在请求完成之后会在ResponseHandler#handleResponse方法中执行相应责任链, 该责任链的每一个节点在feign框架中都可以看作是一个响应拦截器

拦截器应用

请求拦截器

public interface 
<think> 我们正在讨论Retrofit拦截器的使用。用户的问题集中在如何进行请求拦截响应拦截。根据之前的对话历史参考资料,我们可以总结如下: 参考资料[1]展示了使用Retrofit进行网络请求的代码示例,并提到使用拦截器统一打印请求响应的JSON。参考资料[2]说明拦截器用于拦截请求并做处理,且提供了一个GitHub示例链接。参考资料[3]给出了一个拦截器的具体实现(AuthInterceptor)以及如何配置拦截器到OkHttpClient中。 根据这些信息,我们可以这样组织回答: 1. 解释拦截器在Retrofit中的作用:位于请求发送前响应返回后的处理点。 2. 说明如何创建拦截器:通过实现Interceptor接口,重写intercept方法。 3. 在intercept方法中,我们可以: - 在调用chain.proceed(request)之前对请求进行修改(请求拦截) - 在调用chain.proceed(request)之后对响应进行修改(响应拦截) 4. 配置拦截器到OkHttpClient,并设置到Retrofit中。 注意:参考资料[3]中有一个添加统一请求头的例子(AuthInterceptor),我们可以用这个例子说明请求拦截。对于响应拦截,我们可以举一个处理响应体的例子,比如统一处理错误码。 另外,需要注意的是,拦截器分为应用拦截器(addInterceptor)网络拦截器(addNetworkInterceptor)。这里我们主要讨论应用拦截器(因为它能拦截所有请求响应,包括缓存响应)。 我们还可以给出一个日志拦截器的例子,因为参考资料[1]提到统一打印请求响应的json,我们可以实现一个打印请求响应信息的拦截器。 最后,按照要求,我们需要在回答末尾生成相关问题,并注意引用格式。 下面开始组织回答: </think> ### Retrofit 请求拦截响应拦截实现详解 #### 一、核心实现原理 Retrofit 通过 OkHttp 的 `Interceptor` 接口实现拦截机制,核心方法是: ```java public interface Interceptor { Response intercept(Chain chain) throws IOException; } ``` - **请求拦截**:在 `chain.proceed()` 前操作 `Request` 对象 - **响应拦截**:在 `chain.proceed()` 后操作 `Response` 对象 #### 二、基础拦截器实现 ##### 1. 请求日志拦截器 ```java public class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { // 请求拦截:打印请求信息 Request request = chain.request(); Log.d("REQUEST", "URL: " + request.url() + "\nHeaders: " + request.headers()); // 执行请求 Response response = chain.proceed(request); // 响应拦截:打印响应信息 Log.d("RESPONSE", "Code: " + response.code() + "\nBody: " + response.body().string()); return response; } } ``` ##### 2. 认证拦截器(请求拦截) ```java public class AuthInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); // 添加统一认证头 Request newRequest = original.newBuilder() .header("Authorization", "Bearer token123") .build(); return chain.proceed(newRequest); // 执行修改后的请求 } } ``` #### 三、高级应用场景 ##### 1. 响应统一处理(状态码拦截) ```java public class StatusInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Response response = chain.proceed(chain.request()); // 响应拦截:统一处理401错误 if (response.code() == 401) { refreshToken(); // 刷新Token逻辑 return chain.proceed(chain.request()); // 重新发起请求 } return response; } } ``` ##### 2. 动态修改请求参数 ```java public class ParamsInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); // 添加时间戳参数 HttpUrl newUrl = original.url().newBuilder() .addQueryParameter("timestamp", String.valueOf(System.currentTimeMillis())) .build(); Request newRequest = original.newBuilder().url(newUrl).build(); return chain.proceed(newRequest); } } ``` #### 四、配置与使用 ```java // 创建拦截器实例 OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new LoggingInterceptor()) // 日志拦截.addInterceptor(new AuthInterceptor()) // 认证拦截.addNetworkInterceptor(new StatusInterceptor()) // 网络层拦截.build(); // 配置Retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); ``` > **关键点**: > 1. `addInterceptor()` 优先处理原始请求,最后处理响应 > 2. `addNetworkInterceptor()` 在建立网络连接前触发 > 3. 拦截器按添加顺序执行(认证拦截器应置于日志拦截器前) #### 五、注意事项 1. **响应体复用问题**: ```java // 正确读取响应体方式 ResponseBody responseBody = response.body(); String bodyString = responseBody.string(); // 只能调用一次 // 重建响应体 Response newResponse = response.newBuilder() .body(ResponseBody.create(responseBody.contentType(), bodyString)) .build(); ``` 2. **性能优化**: - 避免在拦截器中进行阻塞操作 - 耗时操作使用子线程(如加密解密) 3. **错误处理**: ```java try { return chain.proceed(request); } catch (SocketTimeoutException e) { // 处理超时 } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

uncleqiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值