一、通过官方文档对Interceptor的介绍,我们可以得知Interceptor主要功能有两个:
1,重写请求:可以添加、移除、替换请求头。也可以改造只有一个请求体的请求的请求体(这句话有点拗口),例如你可以添加一个用于压缩请求体的应用拦截器,前提是你的web服务器支持请求体的压缩;
2,重写响应:可以重写响应头并转换响应体。这通常比重写请求头更危险,因为它可能违反了web服务器的期望。如果您处于棘手的情况并准备应对后果,重写响应标头是解决问题的有效方法。例如,您可以修复服务器配置错误的Cache-Control响应头,以实现更好的响应缓存
一般来说我们重写请求的情况会比较多一点,先看看官方是如何实现Interceptor的:
第一个是一个简单的输出请求及响应日志的Interceptor
-
class LoggingInterceptor implements Interceptor {
-
@Override
-
public
Response intercept(Interceptor.Chain chain) throws IOException {
-
Request
request = chain.
request();
-
-
long t1 = System.nanoTime();
-
logger.info(
String.format(
"Sending request %s on %s%n%s",
-
request.url(), chain.connection(),
request.headers()));
-
-
Response
response = chain.proceed(
request);
-
-
long t2 = System.nanoTime();
-
logger.info(
String.format(
"Received response for %s in %.1fms%n%s",
-
response.
request().url(), (t2 - t1) /
1e6d,
response.headers()));
-
-
return
response;
-
}
-
}
实现interceptor我们可以通过Request request = chain.request();获取原始的请求Request对象,这里我们可以理解为Okhttp将原始的请求拦截了,这样就可以输出原始的请求地址,请求头等信息。然后调用chain.proceed(request),再将原始请求发送出去,并获取响应结果Resonse response,这里我们可以理解为将拦截的请求重新发送出去!有了resonse对象自然我们就可以输出和响应结果相关的信息。
第二个例子是压缩请求体的一个拦截器(这里官方反复强调服务端一定要支持请求体压缩,否则服务端可能无法解析请求体)
-
/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
-
final
class GzipRequestInterceptor implements Interceptor {
-
@Override
-
public Response intercept(Interceptor.Chain chain) throws IOException {
-
Request originalRequest = chain.request();
-
if (originalRequest.body() ==
null || originalRequest.header(
"Content-Encoding") !=
null) {
-
return chain.proceed(originalRequest);
-
}
-
-
Request compressedRequest = originalRequest.newBuilder()
-
.header(
"Content-Encoding",
"gzip")
-
.method(originalRequest.method(), gzip(originalRequest.body()))
-
.build();
-
return chain.proceed(compressedRequest);
-
}
-
-
private RequestBody gzip(final RequestBody body) {
-
return
new RequestBody() {
-
@Override
-
public MediaType contentType() {
-
return body.contentType();
-
}
-
-
@Override
-
public long contentLength() {
-
return -
1;
// We don't know the compressed length in advance!
-
}
-
-
@Override
-
public void writeTo(BufferedSink sink) throws IOException {
-
BufferedSink gzipSink = Okio.buffer(
new GzipSink(sink));
-
body.writeTo(gzipSink);
-
gzipSink.close();
-
}
-
};
-
}
-
}
同样的也是先获取原始请求Request originalRequest = chain.request();然后在通过原始请求构造新的请求对象
Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), gzip(originalRequest.body()))
.build();
新的请求对象的请求体是对原始的请求体的压缩gzip(originalRequest.body())
最后在将新的请求compressedRequest发送到服务端。
二、那么我们就可以依葫芦画瓢自己动手实现一个添加SessionId请求头的Interceptor直接贴上代码
-
public
class SimpleHeaderInterceptor implements Interceptor {
-
-
@Override
-
public Response intercept(Chain chain) throws IOException {
-
Request originalRequest = chain.request();
-
if (!TextUtils.isEmpty(Utils.getSessionId())){
-
return chain.proceed(originalRequest);
-
}
-
Request newRequest = originalRequest.newBuilder()
-
.header(
"SessionId", Utils.getSessionId())
-
.build();
-
Response response = chain.proceed(newRequest);
-
return response;
-
}
-
}
三、我们还可以修改请求体,下面别人的修改请求体的例子,功能是给post请求添加一个token参数
-
/**
-
* Created by debanjan on 16/4/17.
-
*/
-
-
public
class TokenInterceptor implements Interceptor {
-
-
public TokenInterceptor(Context context) {
-
this.context = context;
-
}
-
-
@Override
-
public Response intercept(Chain chain) throws IOException {
-
Request request = chain.request();
-
RequestBody requestBody = request.body();
-
String token =
"toku";
//根据需求传入你的token.
-
String subtype = requestBody.contentType().subtype();
-
if(subtype.contains(
"json")){
-
requestBody = processApplicationJsonRequestBody(requestBody, token);
-
}
-
else
if(subtype.contains(
"form")){
-
requestBody = processFormDataRequestBody(requestBody, token);
-
}
-
if(requestBody !=
null) {
-
Request.Builder requestBuilder = request.newBuilder();
-
request = requestBuilder
-
.post(requestBody)
-
.build();
-
}
-
-
return chain.proceed(request);
-
}
-
private String bodyToString(final RequestBody request){
-
try {
-
final RequestBody copy = request;
-
final Buffer buffer =
new Buffer();
-
if(copy !=
null)
-
copy.writeTo(buffer);
-
else
-
return
"";
-
return buffer.readUtf8();
-
}
-
catch (
final IOException e) {
-
return
"did not work";
-
}
-
}
-
private RequestBody processApplicationJsonRequestBody(RequestBody requestBody,String token){
-
String customReq = bodyToString(requestBody);
-
try {
-
JSONObject obj =
new JSONObject(customReq);
-
obj.put(
"token", token);
-
return RequestBody.create(requestBody.contentType(), obj.toString());
-
}
catch (JSONException e) {
-
e.printStackTrace();
-
}
-
return
null;
-
}
-
private RequestBody processFormDataRequestBody(RequestBody requestBody, String token){
-
RequestBody formBody =
new FormBody.Builder()
-
.add(
"token", token)
-
.build();
-
String postBodyString = bodyToString(requestBody);
-
postBodyString += ((postBodyString.length() >
0) ?
"&" :
"") + bodyToString(formBody);
-
return RequestBody.create(requestBody.contentType(), postBodyString);
-
}
-
-
}