springcloud feign调用第三方接口,spring cloud feign使用

  springcloud feign调用第三方接口,spring cloud feign使用

  

目录

分析解决按官方修改的示例:

 

  #中间服务器客户端。javaimport feign .参数导入org。spring框架。云。打开假装。假装客户;导入org。spring框架。网络。绑定。注释。请求映射;导入org。spring框架。网络。绑定。注释。请求方法;@ FeignClient(value= edu-中间服务器)公共接口中间服务器客户端{ @请求映射(value=/test/header ,method=RequestMethod .GET)@ Headers({ userInfo : { userInfo } })对象头测试(@ Param( userInfo )字符串userInfo);}提示错误:

  Java。郎。illegalargumentexception :方法得到不能有请求体。

  

分析

通过断点调试发现假装发请求时把用户信息参数当成了主体数据来处理,而okhttp3会检测得到请求不允许有正文(其他类型的请求哪怕不报错,但因为不是设置到请求头,依然不满足需求)。

 

  查阅官方文档里是通过合同(假装。合同违约)来解析注解的:

  假装注释定义了接口和底层客户端应该如何工作之间的契约假装的默认契约定义了以下注释:

  批注接口目标用法@ requestlinemethod为请求定义HttpMethod和UriTemplate .表达式,花括号{表情}中的值使用它们对应的@Param注释参数进行解析@ ParamParameterDefines定义一个模板变量,其值将用于按名称解析相应的模板表达式@HeadersMethod,type定义一个标题模板.尿酸模板的变体。它使用@Param注释值来解析相应的表达式。当用于类型时,模板将应用于每个请求。当在方法上使用时,模板将只应用于带注释的方法@ QueryMapParameterDefines定义名称-值对的映射,或波乔,以扩展为查询字符串@ HeaderMapParameterDefines定义名称-值对的映射,以扩展到超文本传送协议(Hyper Text Transport Protocol的缩写)头@ BodyMethodDefines定义一个模板,类似于尿酸模板和HeaderTemplate它使用@Param批注值来解析相应的表达式。从自动配置类找到使用的是春天的云的SpringMvcContract(用来解析@Reque

  stMapping相关的注解),而这个注解并不会处理解析上面列的注解

  

@Configurationpublic class FeignClientsConfiguration {@Bean@ConditionalOnMissingBeanpublic Contract feignContract(ConversionService feignConversionService) {return new SpringMvcContract(this.parameterProcessors, feignConversionService);}

 

  

解决

原因找到了:spring cloud使用了自己的SpringMvcContract来解析注解,导致默认的注解解析方式失效。 解决方案自然就是重新解析处理feign的注解,这里通过自定义Contract继承SpringMvcContract再把Feign.Contract.Default解析逻辑般过来即可(重载的方法是在SpringMvcContract基础上做进一步解析,否则Feign对RequestMapping相关对注解解析会失效)

 

  代码如下(此处只对@Headers、@Param重新做了解析):

  

#FeignCustomContract.javaimport feign.Headers;import feign.MethodMetadata;import feign.Param;import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;import org.springframework.cloud.openfeign.support.SpringMvcContract;import org.springframework.core.convert.ConversionService;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.util.*;import static feign.Util.checkState;import static feign.Util.emptyToNull;public class FeignCustomContract extends SpringMvcContract { public FeignCustomContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors, ConversionService conversionService) { super(annotatedParameterProcessors, conversionService); } @Override protected void processAnnotationOnMethod(MethodMetadata data, Annotation methodAnnotation, Method method) { //解析mvc的注解 super.processAnnotationOnMethod(data, methodAnnotation, method); //解析feign的headers注解 Class<? extends Annotation> annotationType = methodAnnotation.annotationType(); if (annotationType == Headers.class) { String[] headersOnMethod = Headers.class.cast(methodAnnotation).value(); checkState(headersOnMethod.length > 0, "Headers annotation was empty on method %s.", method.getName()); data.template().headers(toMap(headersOnMethod)); } } @Override protected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) { boolean isMvcHttpAnnotation = super.processAnnotationsOnParameter(data, annotations, paramIndex); boolean isFeignHttpAnnotation = false; for (Annotation annotation : annotations) { Class<? extends Annotation> annotationType = annotation.annotationType(); if (annotationType == Param.class) { Param paramAnnotation = (Param) annotation; String name = paramAnnotation.value(); checkState(emptyToNull(name) != null, "Param annotation was empty on param %s.", paramIndex); nameParam(data, name, paramIndex); isFeignHttpAnnotation = true; if (!data.template().hasRequestVariable(name)) { data.formParams().add(name); } } } return isMvcHttpAnnotation isFeignHttpAnnotation; } private static Map<String, Collection<String>> toMap(String[] input) { Map<String, Collection<String>> result = new LinkedHashMap<String, Collection<String>>(input.length); for (String header : input) { int colon = header.indexOf(:); String name = header.substring(0, colon); if (!result.containsKey(name)) { result.put(name, new ArrayList<String>(1)); } result.get(name).add(header.substring(colon + 1).trim()); } return result; }}
#FeignCustomConfiguration.javaimport feign.Contract;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.convert.ConversionService;import java.util.ArrayList;import java.util.List;@Configurationpublic class FeignCustomConfiguration { @Autowired(required = false) private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>(); @Bean @ConditionalOnProperty(name = "feign.feign-custom-contract", havingValue = "true", matchIfMissing = true) public Contract feignContract(ConversionService feignConversionService) { return new FeignCustomContract(this.parameterProcessors, feignConversionService); }

改完马上进行新一顿的操作, 看请求日志已经设置成功,响应OK!:

 

  

请求: {"type":"OKHTTP_REQ","uri":"/test/header","httpMethod":"GET","header":"{"accept":["/"],"userinfo":["{"userId":"sssss","phone":"13544445678],"x-b3-parentspanid":["e49c55484f6c19af"],"x-b3-sampled":["0"],"x-b3-spanid":["1d131b4ccd08d964"],"x-b3-traceid":["9405ce71a13d8289"]}","param":""}

 

  

响应 {"type":"OKHTTP_RESP","uri":"/test/header","respStatus":0,"status":200,"time":5,"header":"{"cache-control":["no-cache,no-store,max-age=0,must-revalidate"],"connection":["keep-alive"],"content-length":["191"],"content-type":["application/json;charset=UTF-8"],"date":["Fri,11Oct201913:02:41GMT"],"expires":["0"],"pragma":["no-cache"],"x-content-type-options":["nosniff"],"x-frame-options":["DENY"],"x-xss-protection":["1;mode=block"]}"}

 

  

feign官方链接

 

  spring cloud feign 链接

  (另一种实现请求头的方式:实现RequestInterceptor,但是存在hystrix线程切换的坑)

  到此这篇关于SpringCloud中分析讲解Feign组件添加请求头有哪些坑梳理的文章就介绍到这了,更多相关SpringCloud Feign组件内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: