0%

Spring Cloud 版本升级为 Greenwich,Feign 遇到的问题

Feign 来调用 Get 请求, 参数为 POJO 类时需要添加 @SpringQueryMap 注解,因此 Spring Cloud 版本从 Finchley 升级到 Greenwich
注意@SpringQueryMap 注解对于 POJO 类中的 Date、LocalDate、LocalDateTime 字段无法按照 @JsonFormat 的格式进行序列化

  1. 服务启动失败,报错已经定义了具有该名称的 Bean

    错误信息

    1
    The bean 'FeignClientSpecification' could not be registered. A bean with that name has already been defined and overriding is disabled.

    解决办法

    @FeignClient 注解上添加 contextId 属性,配置了 contextId 就会用 contextId,如果没有配置就会去 value 然后是 name 最后是 serviceId。默认都没有配置,当出现一个服务有多个 Feign Client 的时候就会报错了

    参考

  2. 没有 POJO 类的父类的属性

    解决办法

    添加如下配置

    1
    2
    3
    4
    5
    6
    @Bean
    public Feign.Builder feignBuilder() {
    return Feign.builder()
    .queryMapEncoder(new BeanQueryMapEncoder())
    .retryer(Retryer.NEVER_RETRY);
    }

    参考

  3. 返回结果为 JSON,但是 ContentType 不符

    错误信息

    1
    Could not extract response: no suitable HttpMessageConverter found for response type [class com.alibaba.fastjson.JSONObject] and content type [text/html;charset=utf-8]

    解决办法

    添加如下配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Bean
    public Decoder feignDecoder(){
    return new SpringDecoder(() -> new HttpMessageConverters(new TextMessageConverter()));
    }

    public static class TextMessageConverter extends MappingJackson2HttpMessageConverter {
    public TextMessageConverter(){
    List<MediaType> mediaTypes = new ArrayList<>();
    mediaTypes.add(MediaType.TEXT_PLAIN);
    mediaTypes.add(MediaType.TEXT_HTML);
    setSupportedMediaTypes(mediaTypes);
    }
    }
  4. 开发时查看 Feign 请求日志

    application 配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    logging:
    level:
    root: DEBUG
    feign:
    client:
    config:
    default:
    loggerLevel: FULL
  5. Feign 请求时携带原请求头参数——请求 ID

    当你的 feign 开启了 hystrix 功能,如果开启了,需要把 hystrix 的策略进行修改,默认是 THREAD 的,这个级别时 ThreadLocal 是空的

    application 配置文件

    1
    2
    3
    4
    5
    6
    hystrix:
    command:
    default:
    execution:
    isolation:
    strategy: SEMAPHORE

    拦截器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class OkHttpTokenInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    String requestId = attributes.getRequest().getHeader(RequestConstants.X_REQUEST_ID);
    return chain.proceed(chain.request()
    .newBuilder()
    .header(RequestConstants.X_REQUEST_ID, requestId)
    .build());
    }
    }