• idea本地运行正常,打包部署以后openFeign调用失败,返回为null,以及报错406


    上次成功把项目打包以后,运行也正常,但是在一个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添加、传递请求头

  • 相关阅读:
    Flowable工作流
    【软件安装】Windows系统中使用miniserve搭建一个文件服务器
    深入探索:npm详解
    常见变量命名方法:PascalCase, camelCase, hungarian_notation, kebab-case
    为什么InnoDB选择B+树而不是红黑树作为索引结构?
    概率论_概率公式中的分号(;)、逗号(,)、竖线(|) 及其优先级
    Go 使用环境变量
    八叉树的范围和射线检测
    CLR内存管理机制与IDisposable对象的GC原理
    HTML5--全局属性--事件
  • 原文地址:https://blog.csdn.net/weixin_42260782/article/details/127107238