首页 开发教程 关于openfeign的一个有趣的问题

关于openfeign的一个有趣的问题

开发教程 2025年12月4日
590 浏览

一、问题背景

需要调用第三方和风天气api,获取天气信息
编写了如下使用openfeign调用的接口
image.png

二、问题描述

1、直接通过apifox调用第三方api,没问题
image.png

2、代码中直接通过okhttp调用第三方api,没问题
image.png

3、使用上述的feign调用第三方api,产生2个问题,问题1:401(==偶现==)、问题2:乱码(==必现==),而通过断点排查,调用api的header和参数都是正确的
feign.FeignException$Unauthorized: [401] during [GET] to [] [IWeatherApiService#getWeatherNow(String,String)]: [��U̱� �_!�ZA\'6W ���r�84�鿋n�ox3 31��8��n��@��B�5&�S?^�$\"kOw��X��G�;֞�UͮJ$NoТ$�w��s@qih�o�Y�w�(�[S��}��֫��j��cV��HE4,���N��] at feign.FeignException.clientErrorStatus(FeignException.java:197)

三、问题原因

3.1、问题1:乱码

1、这个第三方api的响应开启了gzip压缩,响应体是 gzip 压缩的
image.png

2、Feign 默认使用 JDK 自带的 HttpURLConnection 作为 HTTP Client,不支持处理gizp
企业微信截图_17636033284560.png

3.2、问题2:401

1、和风天气支持header中放入Authorization的认证方式
2、我们服务依赖的feign的基础服务中,实现了RequestInterceptor,重写了其apply方法,将我们的一些信息放入了header,其中,有些场景会有Authorization放入,而这个拦截器是在我们放入之后,因此会将我们的认证信息覆盖掉
因此就出现了401

四、问题解决

4.1、乱码问题解决

关于openfeign的一个有趣的问题
==将HTTP Client换为okhttp==

feign:
  okhttp:
    enabled: true
    max-connections: 200
    max-connections-per-route: 50

4.2、401问题解决

4.2.1、方式1:覆盖feign的基础服务中的拦截器

  • 编写拦截器,认证信息放入header
public class WeatherFeignRequestInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header(\"Authorization\", \"1111\");
    }
}
  • 编写配置文件
@Configuration
public class WeatherFeignConfig {
    // 注意这里方法名需要跟依赖的项目的拦截器的配置文件中的一样,这样是起到覆盖作用的重要环节
    @Bean
    public RequestInterceptor requestInterceptor() {
        return new WeatherFeignRequestInterceptor();
    }
}
  • feignClient指定config
    image.png

这样的话,就会覆盖feign的基础服务中的拦截器,仅使用我们写的这个拦截器,就不会出现Authorization被覆盖的问题了,也就不会出现401了

4.2.2、方式2:调整拦截器执行顺序,把我们的拦截器放在最后面

  • 修改feign的基础服务中的拦截器
public class BaseFeignRequestInterceptor implements RequestInterceptor, Ordered {
    public void apply(RequestTemplate requestTemplate) {

    }

    public int getOrder() {
        return 2147483547;
    }
}
  • 当前服务的拦截器增加排序
@Slf4j
public class WeatherApiFeignRequestInterceptor implements RequestInterceptor, Ordered {

    private static final String WEATHER_API_SERVICE = \"weatherApiService\";

    @Override
    public void apply(RequestTemplate template) {
        // 非天气服务接口,不处理
        if (!WEATHER_API_SERVICE.equalsIgnoreCase(template.feignTarget().name())) {
            return;
        }
        // 清空所有现有的请求头
        template.headers(null);
        // 只添加你需要的请求头
        template.header(\"Authorization\", 11111);
        template.header(\"Content-Type\", \"application/json\");
    }

    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE - 99;
    }
}
  • 编写配置文件
@Configuration
public class WeatherFeignConfig {
    // 这里方法名随便写
    @Bean
    public RequestInterceptor weatherRequestInterceptor() {
        return new WeatherFeignRequestInterceptor();
    }
}

如此,这个两个拦截器都会生效,不过我们自定义的拦截器会更晚执行,就不会出现我们的认证信息被覆盖的问题了

发表评论
暂无评论

还没有评论呢,快来抢沙发~

客服

点击联系客服 点击联系客服

在线时间:09:00-18:00

关注微信公众号

关注微信公众号
客服电话

400-888-8888

客服邮箱 122325244@qq.com

手机

扫描二维码

手机访问本站

扫描二维码
搜索