一、通过官方文档对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); } }