feign 调用返回值为void接口,抛出了异常也不报错问题处理
在开发阶段发现个问题,对于那些不存在返回值的方法而言,无论响应正常与否,还是出现异常情况,都能够得到妥善处理。然而,在@FeiginClient
注解所标识的情况里,当方法的返回值为void
时,即便对方的接口抛出了异常,客户端依旧会收到成功的信息反馈。经过排查后发现,在调用无返回值的方法时,Feign 的解码器并未执行。
通过调试来查看接口的调用栈情况,发现接口在执行的过程中,会经由一个名为AsyncResponseHandler
的类进行处理,随后会执行一个用于判断是否为void
类型的方法isVoidType
,从表面来看,这与我们所碰到的问题存在关联。
进入AsyncResponseHandler,找到这个方法
@Experimental
class AsyncResponseHandler {
void handleResponse(CompletableFuture<Object> resultFuture, String configKey, Response response, Type returnType, long elapsedTime) {
if (response.status() >= 200 && response.status() < 300) {
if (this.isVoidType(returnType)) {
resultFuture.complete((Object)null);
} else {
result = this.decode(response, returnType);
shouldClose = this.closeAfterDecode;
resultFuture.complete(result);
}
}
}
在使用Feign客户端进行HTTP请求时,如果你遇到的问题是调用返回值为void
的方法时不会报错,这通常是由于Feign的默认行为导致的。Feign是一个声明式的Web服务客户端,它使得编写Web服务客户端变得更加简单。在Feign中,当你定义一个接口方法返回类型为void
时,Feign会默认使用void
作为方法的返回值。这意味着,当你调用一个返回类型为void
的方法时,Feign会尝试执行HTTP请求,并且在请求完成后不会返回任何值(即没有返回值)。
为什么返回值为void
不会报错?
这是因为Feign在设计时考虑到了多种可能的场景。例如,某些HTTP请求可能仅仅是用来触发某些操作(如发送消息、修改状态等),而这些操作的成功与否可能仅仅通过HTTP状态码来体现(例如200 OK表示成功,400 Bad Request表示失败)。在这种情况下,返回类型为void
是合适的,因为它不需要返回额外的数据来指示操作的结果。
如何确保操作成功?
虽然Feign不会因为返回类型为void
而抛出错误,但你可以通过以下几种方式来确保操作的正确性:
-
检查HTTP响应状态码:
你可以通过捕获异常或者在调用方法后检查响应对象的状态码来确保请求成功。例如,你可以在调用方法后检查响应的HTTP状态码:
Response response = feignClient.yourVoidMethod();
if (response.status() == 200) {
// 操作成功
} else {
// 处理错误
}
-
使用
@ResponseStatus
注解:使用的是Spring Cloud OpenFeign,你可以在接口方法上使用
@ResponseStatus
注解来指定期望的HTTP状态码。如果实际返回的状态码与期望的不符,Spring将抛出异常。@RequestMapping(method = RequestMethod.POST, value = "/yourEndpoint")
@ResponseStatus(HttpStatus.OK)
void yourVoidMethod();
-
自定义异常处理:
你可以通过实现
ErrorDecoder
来自定义错误处理逻辑,从而在接收到特定状态码时抛出自定义异常。@Bean
public ErrorDecoder errorDecoder() {
return new ErrorDecoder() {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() >= 400) {
return new FeignException(methodKey, response);
}
return null; // 不抛出异常,保持默认行为
}
};
}