springcloud feign okhttp3

一、通过官方文档对Interceptor的介绍,我们可以得知Interceptor主要功能有两个:

1,重写请求:可以添加、移除、替换请求头。也可以改造只有一个请求体的请求的请求体(这句话有点拗口),例如你可以添加一个用于压缩请求体的应用拦截器,前提是你的web服务器支持请求体的压缩;

2,重写响应:可以重写响应头并转换响应体。这通常比重写请求头更危险,因为它可能违反了web服务器的期望。如果您处于棘手的情况并准备应对后果,重写响应标头是解决问题的有效方法。例如,您可以修复服务器配置错误的Cache-Control响应头,以实现更好的响应缓存

一般来说我们重写请求的情况会比较多一点,先看看官方是如何实现Interceptor的:

第一个是一个简单的输出请求及响应日志的Interceptor


 
 
  1. class LoggingInterceptor implements Interceptor {
  2. @Override
  3. public Response intercept(Interceptor.Chain chain) throws IOException {
  4. Request request = chain. request();
  5. long t1 = System.nanoTime();
  6. logger.info( String.format( "Sending request %s on %s%n%s",
  7. request.url(), chain.connection(), request.headers()));
  8. Response response = chain.proceed( request);
  9. long t2 = System.nanoTime();
  10. logger.info( String.format( "Received response for %s in %.1fms%n%s",
  11. response. request().url(), (t2 - t1) / 1e6d, response.headers()));
  12. return response;
  13. }
  14. }

实现interceptor我们可以通过Request request = chain.request();获取原始的请求Request对象,这里我们可以理解为Okhttp将原始的请求拦截了,这样就可以输出原始的请求地址,请求头等信息。然后调用chain.proceed(request),再将原始请求发送出去,并获取响应结果Resonse response,这里我们可以理解为将拦截的请求重新发送出去!有了resonse对象自然我们就可以输出和响应结果相关的信息。

第二个例子是压缩请求体的一个拦截器(这里官方反复强调服务端一定要支持请求体压缩,否则服务端可能无法解析请求体)


 
 
  1. /** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
  2. final class GzipRequestInterceptor implements Interceptor {
  3. @Override
  4. public Response intercept(Interceptor.Chain chain) throws IOException {
  5. Request originalRequest = chain.request();
  6. if (originalRequest.body() == null || originalRequest.header( "Content-Encoding") != null) {
  7. return chain.proceed(originalRequest);
  8. }
  9. Request compressedRequest = originalRequest.newBuilder()
  10. .header( "Content-Encoding", "gzip")
  11. .method(originalRequest.method(), gzip(originalRequest.body()))
  12. .build();
  13. return chain.proceed(compressedRequest);
  14. }
  15. private RequestBody gzip(final RequestBody body) {
  16. return new RequestBody() {
  17. @Override
  18. public MediaType contentType() {
  19. return body.contentType();
  20. }
  21. @Override
  22. public long contentLength() {
  23. return - 1; // We don't know the compressed length in advance!
  24. }
  25. @Override
  26. public void writeTo(BufferedSink sink) throws IOException {
  27. BufferedSink gzipSink = Okio.buffer( new GzipSink(sink));
  28. body.writeTo(gzipSink);
  29. gzipSink.close();
  30. }
  31. };
  32. }
  33. }

同样的也是先获取原始请求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直接贴上代码


 
 
  1. public class SimpleHeaderInterceptor implements Interceptor {
  2. @Override
  3. public Response intercept(Chain chain) throws IOException {
  4. Request originalRequest = chain.request();
  5. if (!TextUtils.isEmpty(Utils.getSessionId())){
  6. return chain.proceed(originalRequest);
  7. }
  8. Request newRequest = originalRequest.newBuilder()
  9. .header( "SessionId", Utils.getSessionId())
  10. .build();
  11. Response response = chain.proceed(newRequest);
  12. return response;
  13. }
  14. }

三、我们还可以修改请求体,下面别人的修改请求体的例子,功能是给post请求添加一个token参数


 
 
  1. /**
  2. * Created by debanjan on 16/4/17.
  3. */
  4. public class TokenInterceptor implements Interceptor {
  5. public TokenInterceptor(Context context) {
  6. this.context = context;
  7. }
  8. @Override
  9. public Response intercept(Chain chain) throws IOException {
  10. Request request = chain.request();
  11. RequestBody requestBody = request.body();
  12. String token = "toku"; //根据需求传入你的token.
  13. String subtype = requestBody.contentType().subtype();
  14. if(subtype.contains( "json")){
  15. requestBody = processApplicationJsonRequestBody(requestBody, token);
  16. }
  17. else if(subtype.contains( "form")){
  18. requestBody = processFormDataRequestBody(requestBody, token);
  19. }
  20. if(requestBody != null) {
  21. Request.Builder requestBuilder = request.newBuilder();
  22. request = requestBuilder
  23. .post(requestBody)
  24. .build();
  25. }
  26. return chain.proceed(request);
  27. }
  28. private String bodyToString(final RequestBody request){
  29. try {
  30. final RequestBody copy = request;
  31. final Buffer buffer = new Buffer();
  32. if(copy != null)
  33. copy.writeTo(buffer);
  34. else
  35. return "";
  36. return buffer.readUtf8();
  37. }
  38. catch ( final IOException e) {
  39. return "did not work";
  40. }
  41. }
  42. private RequestBody processApplicationJsonRequestBody(RequestBody requestBody,String token){
  43. String customReq = bodyToString(requestBody);
  44. try {
  45. JSONObject obj = new JSONObject(customReq);
  46. obj.put( "token", token);
  47. return RequestBody.create(requestBody.contentType(), obj.toString());
  48. } catch (JSONException e) {
  49. e.printStackTrace();
  50. }
  51. return null;
  52. }
  53. private RequestBody processFormDataRequestBody(RequestBody requestBody, String token){
  54. RequestBody formBody = new FormBody.Builder()
  55. .add( "token", token)
  56. .build();
  57. String postBodyString = bodyToString(requestBody);
  58. postBodyString += ((postBodyString.length() > 0) ? "&" : "") + bodyToString(formBody);
  59. return RequestBody.create(requestBody.contentType(), postBodyString);
  60. }
  61. }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值