上次成功把项目打包以后,运行也正常,但是在一个openFeign调用的接口里面出现奇怪的现象:

admin模块中我定义的获取当前用户的方法getCurrentUser方法来获取当前用户,contract模块中,我使用openFeign调用该方法,然后获取用户的id来查询,但是页面数据为空,这就很奇怪了。

在idea里面启动项目,查询页面数据一切正常,打断点、debug,也确实获取了当前用户的id。就是打包以后,在运行jar包的情况下,openFeign就调用不到了,查看控制台,里面打印的sql,其中的用户id参数竟然是null。

经过百度:
有的说新版的springgateway与openFeign存在版本兼容问题,spring-cloud-starter-gateway 依赖的是 spring-boot-starter-webflux, 但是 OpenFeign 用的是spring-boot-starter-web。
spring-boot-starter-webflux和spring-boot-starter-web 二者只能选一。

必须使用异步调用FeignClient的方式,不能同步调用,或者使用WebClient,原文地址:
FeignClient异步调用

这个方法我没解决,仅供参考,因为被调用方返回值为用户对象User:
在这里插入图片描述
考虑到可能是返回值的问题,调用的返回值没办法被解析?修改接口,使其只返回一个Long类型的id,:
在这里插入图片描述
还是报错Cannot deserialize value of type java.lang.Long from Object value (token JsonToken.START_OBJECT)
在这里插入图片描述

猜测是openFeign返回的是Object类型对象,没办法把它反序列化成Long类型?

反反复复折腾,还报错406feign.FeignException$NotAcceptable的错,
在这里插入图片描述
查到一个原因:可能是Feign在组装Http请求去调用远端服务时 请求头参数有问题,
解决方法:接口上增加参数:produces = MediaType.APPLICATION_JSON_UTF8_VALUE,经过测试。这个已经过时,使用新的代替方案:

被调用方作为生产者,增加属性:produces="application/json; charset=UTF-8"
在这里插入图片描述
调用方client作为消费者,增加属性:consumes = "application/json; charset=UTF-8"
在这里插入图片描述
consumes定义了方法接受的Http的请求类型,produces则定义了Http请求返回的类型。
FeignClient,它的底层实现,就是根据定义的FeignClient,来组装Http请求进行远程调用,

配置完以后,报了新的错:java.lang.NumberFormatException: For input string:,报错信息里面竟然是401,未登录的错,这就有点迷惑了,本地调用都没问题,打个包部署运行,去调用方法,竟然是未登录状态。

原因在于:springcloud open-feign需要添加、传递请求头

当我们feign调用提供者需要携带自定义的请求头,或者想继续传递上游服务的请求头信息时,可进行如下方式处理

1、实现RequestInterceptor,并Configuration注解标记为配置类
2、复写apply 方法,将我们的自定义的请求头 通过header存进去即可
3、可根据请求信息遍历请求头信息,选择是否将上游请求头信息向下游服务传递
4、该配置类需要能被扫包扫到(主启动函数 子侄包路径)

这里我使用配置类的方式,新增配置类FeignConfig:

@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        template.header(headerNames.nextElement(), request.getHeader(headerNames.nextElement()));
        if (headerNames == null) {
            return;
        }
        //处理上游请求头信息,传递时继续携带
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            String values = request.getHeader(name);
            template.header(name, values);
        }
    }
}

打包以后,完美调用

参考链接:springcloud open-feign添加、传递请求头

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐