真实案例:Feign 切换 okhttp 无法生效,被老大骂的有点慌!

这篇具有很好参考价值的文章主要介绍了真实案例:Feign 切换 okhttp 无法生效,被老大骂的有点慌!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

来源:https://www.cnblogs.com/mufeng3421/p/11442412.html

提示:如果只看如何解决问题,请看文章的末尾如何解决这个问题

1. 场景描述

最近项目中使用了feign当做http请求工具来使用、相对于httpclient、resttemplate来说,fegin用起来方便很多。然后项目有httptrace的需求,需要输出请求日志。

所以就开启了feign自己的日志,发现它自带的日志是debug级别才能打印。而且是逐行打印的,看日志非常的不方便。所以需要输出json格式的日志最好。

2.解决步骤

2.1 引入feign依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>${自行选择适合项目的版本}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

这里使用了spring-cloud-openfeing来避免自己手工实现feign的注入,用法上和feign一样

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

2.2 配置feign

在入口类上添加 @EnableFeignClients 注解

@SpringBootApplication
@EnableFeignClients
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

使用feing自己的Contract,方便使用feign自己的注解来声明http接口。这里使用了一个配置类

@Configuration
public class FeignConfig {
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }
}

2.3 声明接口

只需要声明一个带有@FeignClient注解的接口,就声明好了一个Feign的http请求接口

@FeignClient(name = "accessPlatform", url = "${url.access-platform}")
public interface AccessPlatformFeignClient {
    @RequestLine("GET /access-platform/resource")
    List<AccessResource> queryResourceList(@QueryMap Map<String, Object> query);
}

3.切换Feign的客户端为OkHttp

由于feign自带的http客户端实现是HttpURLConnection,没有连接池功能,可配置能力也比较差,因此我们使用okhttp作为底层的http客户端的具体实现。

3.1 引入okhttp的依赖

 <dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-okhttp</artifactId>
    <version>${feign-okhttp.version}</version>
</dependency>

3.2 修改之前的FeignConfig配置类

问题就出在这里、不过先不急,我们继续

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignConfig {
    // 注入feignContract
    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }

    // 注入自定义的okHttpClient
    @Bean
    public okhttp3.OkHttpClient okHttpClient(){
        return new okhttp3.OkHttpClient.Builder()
            .readTimeout(60, TimeUnit.SECONDS)
            .connectTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .connectionPool(new ConnectionPool())
            .build();
    }
}

开启okhttp作为feign的客户端

# application.yml
feign:
    okhttp:
        enabled: true

一切完美、网上的许多博客也都是这么写的。然后它们告诉你已经配置完了?呵呵,你们到底自己试过没有??

3.3 试着请求一下

当然这里出问题了,发出的请求并非来自okhttp,还是默认的JDK的HttpURLConnection,问题出在哪里呢?接着看

4.找出问题所在

我怀疑是feing在注入配置的时候,根本就没有运行关于okhttp的配置

4.1 查看服务启动时feign配置过程

1.将服务根日志级别调整为debug级别

logging:
    level:
    	root: debug

2.启动服务、查看控制台输出

真实案例:Feign 切换 okhttp 无法生效,被老大骂的有点慌!

看到没,okhttp的配置不符合配置运行条件。

3.查询 FeignAutoConfiguration 这个配置类的细节

@Configuration
@ConditionalOnClass({Feign.class})
@EnableConfigurationProperties({FeignClientProperties.class, FeignHttpClientProperties.class})
public class FeignAutoConfiguration {
		// .....其他的配置
  	@Configuration
    @ConditionalOnClass({OkHttpClient.class})
    @ConditionalOnMissingClass({"com.netflix.loadbalancer.ILoadBalancer"})
    @ConditionalOnMissingBean({okhttp3.OkHttpClient.class})
    @ConditionalOnProperty({"feign.okhttp.enabled"})
    protected static class OkHttpFeignConfiguration {
       // ...okhttp的配置
    }

  	// .....其他的配置
}

就是这个自动配置类搞的鬼、当我看到 @ConditionalOnMissingBean({okhttp3.OkHttpClient.class}) 这个注解时,我就明白了。
翻成白话就是,只有当容器中没有OkHttpClient的实例时。他才会运行。如果在 FeignAutoConfiguration之前注入了我们自己定义的OkHttpClient实例,那不好意思,我不干了?无不注入。

5.解决问题

既然自动配置不干,那我们自己动手干。拷贝 FeignAutoConfiguration 配置类中的配置过程,粘贴在FeignConfig配置类中手动注入feign的client。Ok!完美解决。

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureAfter(FeignAutoConfiguration.class)
public class FeignConfig {
//    private okhttp3.OkHttpClient okHttpClient;

    @Bean
    public Contract feignContract() {
        return new feign.Contract.Default();
    }

    @Bean
    @ConditionalOnMissingBean({Client.class})
    public Client feignClient(okhttp3.OkHttpClient client) {
        return new feign.okhttp.OkHttpClient(client);
    }

    @Bean
    @ConditionalOnMissingBean({ConnectionPool.class})
    public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties, OkHttpClientConnectionPoolFactory connectionPoolFactory) {
        Integer maxTotalConnections = httpClientProperties.getMaxConnections();
        Long timeToLive = httpClientProperties.getTimeToLive();
        TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
        return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
    }

    @Bean
    public OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool, FeignHttpClientProperties httpClientProperties) {
        Boolean followRedirects = httpClientProperties.isFollowRedirects();
        Integer connectTimeout = httpClientProperties.getConnectionTimeout();
        Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
        return httpClientFactory.createBuilder(disableSslValidation)
                .connectTimeout((long)connectTimeout, TimeUnit.MILLISECONDS)
                .followRedirects(followRedirects)
                .connectionPool(connectionPool)
                .addInterceptor(new OkHttpLogInterceptor()) // 自定义请求日志拦截器
                .build();
    }
}

6.小结

如果你没有耐心看完所有的过程的话。就记住一句话:用自己手动注入Feign的Client实现,来代替 Feign的自动配置所做的过程就好了。具体的配置请看第5点。

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!文章来源地址https://www.toymoban.com/news/detail-481896.html

到了这里,关于真实案例:Feign 切换 okhttp 无法生效,被老大骂的有点慌!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ElasticSearch删除索引【真实案例】

    项目中使用了ELK技术栈实现了日志管理,但是日志管理功能目前并没有在生产上实际使用。 但ELK程序依然在运行,导致系统磁盘发生告警,剩余可用磁盘不足10%。 所以临时的解决办法是:删除这些没有使用的ES索引数据。 ElasticSearch提供了Web API可以删除索引。详见 删除索引

    2024年02月15日
    浏览(36)
  • 解决pinia中的i18n切换语言不生效的问题

    在我的项目中,使用i18n切换语言后,会进行 router.push 来刷新页面。 但我发现写在store中的选项(我把它们用作下拉框组件的 options ,例如 options=\\\"store.statusOption\\\" ),却并没有切换语言。它们需要我手动刷新页面后才能够切换语言。然而其它组件中的语言切换都很正常。 个人

    2024年02月13日
    浏览(33)
  • 解决swiper在Element-ui的tabs标签页切换时,swiper不生效,以及v-if和v-show不生效,还有左右箭头切换按钮点击无效的情况。

    解决swiper在Element-ui的tabs标签页切换时,swiper不生效,以及v-if和v-show不生效,还有左右箭头切换按钮点击无效的情况。 官网给出的解决方案是,使用observer:swiper4的api地址: https://www.swiper.com.cn/api/observer/218.html. 在切换Element-ui的tabs标签的时候,切换到没有使用Swiper的页面时销

    2024年02月15日
    浏览(61)
  • 【Unity】一键切换是否允许#if UNITY_EDITOR条件编译生效

    在项目中经常会条件编译的方式来让编译器环境和非编译器环境跑不同的代码,但这种方式会让非编译器环境的代码测试变得十分不方便。UNITY_EDITOR也是Unity预定义的宏,不能直接在PlayerSettings里面增加或删除。 用#undef UNITY_EDITOR可以取消unity预定义的UNITY_EDITOR宏,这样就可以

    2024年02月11日
    浏览(35)
  • mac brew安装 node 踩坑日记- n切换node不生效

    最近用了一个旧电脑开发,发现里面node管理混乱,有 nvm 、 n 和 homebrew ,导致切换node 切换不了,开发也有莫名其妙的错误。所以我打算重新装一下node,使用 n 做为管理工具。 1. 删除nvm 2. 删除n 3. 卸载nvm 或者 使用命令行卸载 Node.js 第一步:打开终端,输入以下命令显示 N

    2024年02月07日
    浏览(47)
  • 面试官:如何进行 JVM 调优(附真实案例)

    面试官:在工作中做过 JVM 调优吗?讲讲做过哪些 JVM 调优? 我一个QPS不到10的项目,上次问我缓存穿透缓存雪崩,这次问我 JVM 调优,我是真滴难。 不过大家别慌,热心的我给大家找来了几个满分回答,大家选择合适的使用。 回答1:听好了,下面将是我第一次 JVM 调优。 回

    2024年01月19日
    浏览(57)
  • 台式电脑 windows系统蓝屏解决思路+真实案例

    最近番茄初次装机,遇到了多次蓝屏的情况,周转多次最终还是解决了问题。 写这篇文章,记录一下遇到蓝屏情况,记录做了哪些操作,以及解决问题的思路。 一般电脑发生蓝屏,会有一个错误编码,请及时记录。 有了错误的编码,方便我们有目的性的有针对性去测试问题

    2024年04月23日
    浏览(41)
  • Docker中文件拷贝命令的详细解释与真实案例

    简介: Docker是一种流行的容器化平台,它提供了一种轻量级、可移植的解决方案,用于在不同的环境中部署和运行应用程序。在Docker中,文件拷贝是一个常见的操作,它允许将文件从主机系统复制到容器中,或者从容器中复制到主机系统中。本文将详细解释Docker中文件拷贝相

    2024年02月08日
    浏览(39)
  • 【JDK】二、环境变量从jdk17切换为jdk8后不生效的解决办法

    在学习springboot3时配置了java17的环境变量,但平常工作中使用的还是java8,所以还需要再还原配置。 单还原环境变量配置后,使用 java -version 还是17的问题。 重启后输入java-version 命令 任然 是java17,显然是不对的 是因为我们在安装了jdk17后,默认添加的17的环境变量配置,并且

    2024年02月07日
    浏览(43)
  • IDEA中lombok无法生效的问题

    今天遇到一个很诡异的现象,就是实体类在某些包下编译可以正常通过,在公共包下实体类就编译不通过,@Data注解没有生成对应的Getter和Setter方法。 1. 检查是否安装了lombok插件 确认安装 2. 是否引入到pom文件 确认引入 3. 手动自己生成Getter和Setter方法,公共包下也编译通过,

    2024年02月14日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包