Spring Cloud组件feign支持get请求pojo

出现问题的原因

较早springboot2.1.x版本中,feign是不原生支持get形式的pojo的方式传参的,但是查询的时候,我们遵循restfull Api的开发规范,此时传递的参数,就会接收不到(为null).

解决方案一

升级springboot版本到2.1.x.使用Spring Cloud OpenFeign提供@SpringQueryMap注解,用于将POJO或Map参数注释为查询参数映射。
1.定义一个pojo类


@Setter
@Getter
public  class Params {
     private String param1;
    private String param2;
}



2.以下feign客户端使用注释使用Params该类@SpringQueryMap:

@FeignClient(“demo”)
公共 类 DemoTemplate {

    @GetMapping(path =“/ demo”) 
    String demoEndpoint( @SpringQueryMap Params params);
}

此时会出现一个异常: Method xxx not annotated with HTTP method type (ex. GET, POST),这个是由于 @RequestLine is a core Feign annotation, but you are using the Spring Cloud @FeignClientwhich uses Spring MVC annotations.研究源码发现:在Contract接口中:

   protected MethodMetadata parseAndValidateMetadata(Class targetType, Method method) {
      MethodMetadata data = new MethodMetadata();
      data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));
      data.configKey(Feign.configKey(targetType, method));

      if (targetType.getInterfaces().length == 1) {
        processAnnotationOnClass(data, targetType.getInterfaces()[0]);
      }
      processAnnotationOnClass(data, targetType);


      for (Annotation methodAnnotation : method.getAnnotations()) {
        processAnnotationOnMethod(data, methodAnnotation, method);
      }
      checkState(data.template().method() != null,
          "Method %s not annotated with HTTP method type (ex. GET, POST)",
          method.getName());
      Class[] parameterTypes = method.getParameterTypes();
      Type[] genericParameterTypes = method.getGenericParameterTypes();

      Annotation[][] parameterAnnotations = method.getParameterAnnotations();

意思就是feign 默认使用的是spring mvc 注解(就是RequestMapping 之类的), 所以需要配置自定义的:Contract

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

解决方案二

@Component
@Slf4j
public class FeignCustomRequestInteceptor implements RequestInterceptor {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void apply(RequestTemplate template) {
        if (HttpMethod.GET.toString() == template.method() && template.body() != null) {
            //feign 不支持GET方法传输POJO 转换成json,再换成query
            try {
                Map> map = objectMapper.readValue(template.bodyTemplate(), new TypeReference>>() {

                });
                template.body(null);
                template.queries(map);
            } catch (IOException e) {
                log.error("cause exception", e);
            }
        }
    }

总结

feign调用会有很多的坑坑洼洼,大家多看下文档,或许你的收益会不一样。

你可能感兴趣的:(Spring,Cloud,feign)