zoukankan      html  css  js  c++  java
  • spring cloud feign使用okhttp3

    在Feign中,Client是一个非常重要的组件,Feign最终发送Request请求以及接收Response响应都是由Client组件来完成的。Client在Feign源码中是一个接口,在默认情况下,Client的实现类是Client.Default。Client.Default是由HttpURLConnection来实现网络请求的。另外,Client还支持HttpClient和OkHttp3来进行网络请求。
    HttpURLConnection没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。
    但是做Android的小伙伴早已经淘汰该库了,就是因为其API数量过多过于繁重,使得我们很难在不破坏兼容性的情况下对它进行升级和扩展,因而团队不愿意去维护该库.本章介绍的是由 Square 公司开发的OkHttp,是一个专注于性能和易用性的 HTTP 客户端。

    OkHttp的优点

    okhttp 的设计初衷就是简单和高效,这也是我们选择它的重要原因之一。它的优势如下:

    • 支持 HTTP/2 协议。
    • 允许连接到同一个主机地址的所有请求,提高请求效率。
    • 共享Socket,减少对服务器的请求次数。
    • 通过连接池,减少了请求延迟。
    • 缓存响应数据来减少重复的网络请求。
    • 减少了对数据流量的消耗。
    • 自动处理GZip压缩。

    Feign使用Okhttp

    maven

       <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
                <version>2.0.2.RELEASE</version>
             </dependency>
             <dependency>
                 <groupId>io.github.openfeign</groupId>
                 <artifactId>feign-okhttp</artifactId>
                 <version>10.1.0</version>
             </dependency>
    

    配置文件

    feign.httpclient.enabled=false
    feign.okhttp.enabled=true
    

    配置

    package com.haier.uhome.iot.api.config;
    
    
    import com.haier.uhome.iot.api.interceptors.OkHttpInterceptor;
    import feign.Feign;
    import lombok.extern.slf4j.Slf4j;
    import okhttp3.OkHttpClient;
    import org.springframework.boot.autoconfigure.AutoConfigureBefore;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.cloud.commons.httpclient.OkHttpClientFactory;
    import org.springframework.cloud.openfeign.FeignAutoConfiguration;
    import org.springframework.cloud.openfeign.support.FeignHttpClientProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.concurrent.TimeUnit;
    
    @Configuration
    @ConditionalOnClass(Feign.class)
    @AutoConfigureBefore(FeignAutoConfiguration.class)
    @Slf4j
    public class FeignClientConfig {
    
        private OkHttpClient okHttpClient;
    
        @Bean
        public OkHttpInterceptor okHttpInterceptor(){
            return new OkHttpInterceptor();
        }
    
        //注入okhttp
        @Bean
        public okhttp3.OkHttpClient okHttpClient(OkHttpClientFactory okHttpClientFactory,
                                                 FeignHttpClientProperties httpClientProperties) {
            this.okHttpClient = okHttpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation()).connectTimeout(httpClientProperties.getConnectionTimeout(),TimeUnit.SECONDS)
                    .followRedirects(httpClientProperties.isFollowRedirects())
                    .addInterceptor(okHttpInterceptor())
                    .build();
            return this.okHttpClient;
        }
    }
    

    配置拦截器

    package com.haier.uhome.iot.api.interceptors;
    
    
    import com.haier.uhome.iot.api.utils.CommonConstant;
    import com.haier.uhome.iot.api.utils.ElasticsearchClient;
    import com.haier.uhome.iot.core.util.Jackson;
    import lombok.extern.slf4j.Slf4j;
    import okhttp3.*;
    import okio.Buffer;
    import okio.BufferedSource;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import java.io.EOFException;
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.HashMap;
    
    @Slf4j
    public class OkHttpInterceptor implements HandlerInterceptor, Interceptor {
        @Autowired
        private ElasticsearchClient elasticsearchClient;
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            log.info("进入okhttp拦截器");
            //编码设为UTF-8
            Charset charset = Charset.forName("UTF-8");
            try {
                HashMap esCmdLogMap = new HashMap();
                Request request = chain.request();
                HashMap requestMap = this.getRequestBody(request, charset);
                Response response = chain.proceed(request);
              if(request.url().toString().contains("manage/command")) {
                  log.info(request.url().toString());
                  HashMap responseMap = this.getResponseBody(response, charset);
                  esCmdLogMap.put("requestUrl", request.url().toString());
                  esCmdLogMap.put("request", requestMap);
                  esCmdLogMap.put("deviceId", requestMap.get("deviceId"));
                  esCmdLogMap.put("productCode", requestMap.get("productCode"));
                  esCmdLogMap.put("response", responseMap);
                  long startTime = System.currentTimeMillis();
    //          LocalDateTime rightNow = LocalDateTime.now();
    //          String createTime = rightNow.format(DateTimeFormatter.ISO_DATE);
                  esCmdLogMap.put("cmdTime", startTime);
                  elasticsearchClient.postRquestAsync(CommonConstant.INDEX_DEVICE_CMD, CommonConstant.TYPE_DEVICE_HIST, Jackson.object2JsonStr(esCmdLogMap));
              }
                return response;
            }catch (Exception e){
                throw  e;
            }
        }
    
        private HashMap getResponseBody(Response response,Charset charset) throws IOException {
            ResponseBody responseBody = response.body();
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE);
            Buffer buffer = source.buffer();
            MediaType mediaType = responseBody.contentType();
            if(isPlaintext(buffer)){
                String result = buffer.clone().readString(mediaType.charset(charset));
                HashMap resultMap = Jackson.jsonStr2Object(result,HashMap.class);
                log.info("result:"+result);
                return resultMap;
            }
            return null;
        }
    
        private HashMap getRequestBody(Request request ,Charset charset) {
            RequestBody requestBody = request.body();
            Buffer reqbuffer = new Buffer();
            try {
                requestBody.writeTo(reqbuffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(Charset.forName("UTF-8"));
            }
            //拿到request
            return Jackson.jsonStr2Object(reqbuffer.readString(charset),HashMap.class);
        }
    
        /**
         * Returns true if the body in question probably contains human readable text. Uses a small sample
         * of code points to detect unicode control characters commonly used in binary file signatures.
         */
        static boolean isPlaintext(Buffer buffer) throws EOFException {
            try {
                Buffer prefix = new Buffer();
                long byteCount = buffer.size() < 64 ? buffer.size() : 64;
                buffer.copyTo(prefix, 0, byteCount);
                for (int i = 0; i < 16; i++) {
                    if (prefix.exhausted()) {
                        break;
                    }
                    int codePoint = prefix.readUtf8CodePoint();
                    if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
                        return false;
                    }
                }
                return true;
            } catch (EOFException e) {
                return false; // Truncated UTF-8 sequence.
            }
        }
    
        private boolean bodyEncoded(Headers headers) {
            String contentEncoding = headers.get("Content-Encoding");
            return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity");
        }
    }
    
    定位问题原因* 根据原因思考问题解决方案* 实践验证方案有效性* 提交验证结果
  • 相关阅读:
    trackr: An AngularJS app with a Java 8 backend – Part III
    trackr: An AngularJS app with a Java 8 backend – Part II
    21. Wireless tools (无线工具 5个)
    20. Web proxies (网页代理 4个)
    19. Rootkit detectors (隐形工具包检测器 5个)
    18. Fuzzers (模糊测试器 4个)
    16. Antimalware (反病毒 3个)
    17. Debuggers (调试器 5个)
    15. Password auditing (密码审核 12个)
    14. Encryption tools (加密工具 8个)
  • 原文地址:https://www.cnblogs.com/jimoliunian/p/14676009.html
Copyright © 2011-2022 走看看