前一篇,我们解决了Spring的RestTemplate
在发送Get请求不能传递body,相比RestTemplate
,我们更多的还是采用更方便的申明式服务调用框架Feign。本篇不会介绍Feign,而是解决Feign发送Get请求时仍然不能传递body的问题。
1. 准备
在这里,我使用的Spring boot的版本为1.5.10.RELEASE
,Spring Cloud版本为Edgware.SR3
。
准备三个服务:注册中心、服务生产者、服务消费,这里我们继续使用在 Spring Cloud服务注册中心Eureka定义的三个服务:服务注册中心01-eureka-server
、服务提供者01-service-demo
,同时新建一个服务消费者01-feign-consumer
,使用feign来请求服务而不是ribbon,记得在启动类加上@EnableFeignClients
启用Feign。
1、在服务提供者01-service-demo
添加一个接口,代码如下:
@GetMapping("/hello/user")
public String sayHello(@RequestBody User user) {
return "hello, " + user.getName() + ", give you a gift " + user.getGift();
}
这样,Get请求需要接收body数据。
2、在服务消费者01-feign-consumer
编写如下代码:
(1)在SayHelloClient
中添加如下声明式服务请求:
@FeignClient("hello-service")
public interface SayHelloClient {
@GetMapping(value = "/hello/user")
String sayHello(@RequestBody User user);
}
(2)在SayHelloController
中调用SayHelloClient
:
@RestController
public class SayHelloController {
private static Logger log = LoggerFactory.getLogger(SayHelloController.class);
@Autowired
private ApiProductClient apiProductClient;
@GetMapping("/user")
public String userHello() {
User user = new User();
user.setName("lily");
user.setGift("birthday card");
return sayHelloClient.sayHello(user);
}
}
3、分别启动服务注册中心01-eureka-server
、服务提供者01-service-demo
,服务消费者01-feign-consumer
,浏览器访问http://localhost:9091/user
,后台先错误信息:
feign.FeignException: status 405 reading SayHelloClient#sayHello(User); content:
{"timestamp":1548141786602,"status":405,"error":"Method Not Allowed","exception":"org.springframework.web.HttpRequestMethodNotSupportedException","message":"Request method 'POST' not supported","path":"/hello/user"}
at feign.FeignException.errorStatus(FeignException.java:62) ~[feign-core-9.5.0.jar:na]
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91) ~[feign-core-9.5.0.jar:na]
……
意思是请求的Post方法不被允许,很明显,我们后台必须接收Get请求,而非Post。
2. 原因
同RestTemplate类似,Feign默认情况下也使用的是JDK原生的http请求,同时也支持OkHttp、HttpClient等框架。默认情况下,原生Http请求不允许Get请求传递body,如果传递了body数据,会将当前请求转为Post请求,而实际上我们后台接收的是Get请求,所以抛出上边的异常,所以我们需要换成能够支持的HttpClient。
3. 解决
1、在服务消费者01-feign-consumer
的pom.xml中引入第三方依赖包:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>9.4.0</version>
</dependency>
2、在服务消费者01-feign-consumer
的配置文件中启用httpclient:
# feign use httpclient
feign.httpclient.enabled=true
3、测试:
分别启动服务注册中心01-eureka-server
、服务提供者01-service-demo
,服务消费者01-feign-consumer
,浏览器再次访问http://localhost:9091/user
,可以看到输出了正确的信息:
问题解决。
示例代码: github