传递对象的另一种方法和多参传递
1、GET请求多参数的URL
假设我们请求的URL包含多个参数,例如 http://microservice-provider-user/get?id=1&username=张三 ,要怎么办呢?
我们知道Spring Cloud为Feign添加了Spring MVC的注解支持,那么我们不妨按照Spring MVC的写法尝试一下:
"microservice-provider-user") (publicinterfaceUserFeignClient { value="/get", method=RequestMethod.GET) (publicUserget0(Useruser); }
然而我们测试时会发现该写法不正确,我们将会收到类似以下的异常:
feign.FeignException: status 405 reading UserFeignClient#get0(User); content:
{"timestamp":1482676142940,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/get"}
由异常可知,尽管指定了GET方法,Feign依然会发送POST请求。
正确写法如下
(1) 方法一
name="microservice-provider-user") (publicinterfaceUserFeignClient { value="/get", method=RequestMethod.GET) (publicUserget1( ("id") Longid, ("username") Stringusername); }
这是最为直观的方式,URL有几个参数,Feign接口中的方法就有几个参数。使用@RequestParam注解指定请求的参数是什么。
(2) 方法二
name="microservice-provider-user") (publicinterfaceUserFeignClient { value="/get", method=RequestMethod.GET) (publicUserget2(Map<String, Object>map); }
多参数的URL也可以使用Map去构建
当目标URL参数非常多的时候,可使用这种方式简化Feign接口的编写。
2、POST请求包含多个参数
下面我们来讨论如何使用Feign构造包含多个参数的POST请求。
实际就是坑四,把参数封装成对象传递过去就可以了
总结
Feign的Encoder、Decoder 和 ErrorDecoder
Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。
默认情况下,Feign会将标有@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。
注意,如果在@RequetMapping中的method将请求方式指定为get,那么所有未标注解的参数将会被忽略,例如
value="/group/{groupId}", method=RequestMethod.GET) (voidupdate( ("groupId") IntegergroupId, ("groupName") StringgroupName, DataObjectobj);
此时因为声明的是GET请求没有请求体,所以obj参数就会被忽略。
在Spring Cloud环境下,Feign的Encoder*只会用来编码没有添加注解的参数*。如果你自定义了Encoder, 那么只有在编码obj参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverter类进行解码。只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。
Feign 的 HTTP Client
Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient依赖:
<!--使用ApacheHttpClient替换Feign原生httpclient--><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><dependency><groupId>com.netflix.feign</groupId><artifactId>feign-httpclient</artifactId><version>${feign-httpclient}</version></dependency>
然后在application.properties中添加:
feign.httpclient.enabled=true
通过Feign, 我们能把HTTP远程调用对开发者完全透明,得到与调用本地方法一致的编码体验。这一点与阿里Dubbo中暴露远程服务的方式类似,区别在于Dubbo是基于私有二进制协议,而Feign本质上还是个HTTP客户端。如果是在用Spring Cloud Netflix搭建微服务,那么Feign无疑是最佳选择。