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");
        }
    }
    
    定位问题原因* 根据原因思考问题解决方案* 实践验证方案有效性* 提交验证结果
  • 相关阅读:
    asr相关技术总结
    SLURM 使用基础教程
    FSMN 及其变种 cFSMN DFSMN pyramidal-FSMN
    均方根误差(RMSE),平均绝对误差 (MAE),标准差 (Standard Deviation)
    linux文本编码格式转化 字幕处理
    PyTorch-Kaldi 语音识别工具包
    SRILM Ngram 折扣平滑算法
    awk 调用 shell 命令,并传递参数
    用 scikit-learn 和 pandas 学习线性回归
    逻辑回归 及 实例
  • 原文地址:https://www.cnblogs.com/jimoliunian/p/14676009.html
Copyright © 2011-2022 走看看