1. Overview
1.概述
In this tutorial, we’ll demonstrate how to handle exceptions in Feign. Feign is a powerful tool for micro-service developers, and it supports ErrorDecoder and FallbackFactory for exception handling.
在本教程中,我们将演示如何在Feign>中处理异常。Feign是微服务开发人员的强大工具,它支持ErrorDecoder和FallbackFactory进行异常处理。
2. Maven Dependency
2.Maven的依赖性
To start, let’s create a Spring Boot project by including the spring-cloud-starter-openfeign. The spring-cloud-starter-openfeign includes feign-core dependency within it:
首先,让我们创建一个Spring Boot项目,包括spring-cloud-starter-openfeign。spring-cloud-starter-openfeign包括其中的feign-core依赖项。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.3</version>
</dependency>
Or we can add the feign-core dependency to our pom.xml file:
或者我们可以将feign-core依赖性添加到我们的pom.xml文件。
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.9.1</version>
</dependency>
3. Exception Handling with ErrorDecoder
3. 使用ErrorDecoder的异常处理
We can handle exceptions by configuring ErrorDecoder, which also allows us to customize messages when required. When an error occurs, the Feign client suppresses the original message. To retrieve it, we can write a custom ErrorDecoder. Let’s override the default ErrorDecoder implementation:
我们可以通过配置ErrorDecoder来处理异常,这也允许我们在需要时定制消息。当一个错误发生时,Feign客户端会抑制原始消息。为了检索它,我们可以编写一个自定义的ErrorDecoder。 让我们覆盖一下默认的ErrorDecoder实现。
public class RetreiveMessageErrorDecoder implements ErrorDecoder {
private final ErrorDecoder errorDecoder = new Default();
@Override
public Exception decode(String methodKey, Response response) {
ExceptionMessage message = null;
try (InputStream bodyIs = response.body().asInputStream()) {
ObjectMapper mapper = new ObjectMapper();
message = mapper.readValue(bodyIs, ExceptionMessage.class);
} catch (IOException e) {
return new Exception(e.getMessage());
}
switch (response.status()) {
case 400:
return new BadRequestException(message.getMessage() != null ? message.getMessage() : "Bad Request");
case 404:
return new NotFoundException(message.getMessage() != null ? message.getMessage() : "Not found");
default:
return errorDecoder.decode(methodKey, response);
}
}
}
In the above encoder, we override the default behavior to take more control of the exceptions.
在上面的编码器中,我们覆盖了默认行为,以对异常进行更多的控制。
4. Exception Handling with Fallback
4. 用回调处理异常
We can also handle exceptions by configuring fallback. Let’s create a client first and configure fallback:
我们还可以通过配置fallback来处理异常。让我们先创建一个客户端并配置fallback。
@FeignClient(name = "file", url = "http://localhost:8081",
configuration = FeignSupportConfig.class, fallback = FileUploadClientWithFallbackImpl.class)
public interface FileUploadClientWithFallBack {
@PostMapping(value = "/upload-error", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String fileUpload(@RequestPart(value = "file") MultipartFile file);
}
Now, let’s create FileUploadClientWithFallbackImpl to handle the exceptions according to our requirements:
现在,让我们创建FileUploadClientWithFallbackImpl来根据我们的要求处理异常。
@Component
public class FileUploadClientWithFallbackImpl implements FileUploadClientWithFallBack {
@Override
public String fileUpload(MultipartFile file) {
try {
throw new NotFoundException("hi, something wrong");
} catch (Exception ex) {
if (ex instanceof BadRequestException) {
return "Bad Request!!!";
}
if (ex instanceof NotFoundException) {
return "Not Found!!!";
}
if (ex instanceof Exception) {
return "Exception!!!";
}
return "Successfully Uploaded file!!!";
}
}
}
Let’s now create a simple test to validate fallback option:
现在让我们创建一个简单的测试来验证fallback选项。
@Test(expected = NotFoundException.class)
public void whenFileUploadClientFallback_thenFileUploadError() throws IOException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
File file = new File(classloader.getResource(FILE_NAME).getFile());
Assert.assertTrue(file.exists());
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain",
IOUtils.toByteArray(input));
uploadService.uploadFileWithFallback(multipartFile);
}
5. Exception Handling with FallbackFactory
5. 用FallbackFactory处理异常
We can also handle exceptions by configuring FallbackFactory. Let’s create a client first and configure FallbackFactory:
我们还可以通过配置FallbackFactory来处理异常。让我们先创建一个客户端并配置FallbackFactory。
@FeignClient(name = "file", url = "http://localhost:8081",
configuration = FeignSupportConfig.class, fallbackFactory = FileUploadClientFallbackFactory.class)
public interface FileUploadClient {
@PostMapping(value = "/upload-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String fileUpload(@RequestPart(value = "file") MultipartFile file);
}
Now, let’s create FileUploadClientFallbackFactory to handle the exceptions according to our requirements:
现在,让我们创建FileUploadClientFallbackFactory来根据我们的要求处理异常。
@Component
public class FileUploadClientFallbackFactory implements FallbackFactory<FileUploadClient> {
@Override
public FileUploadClient create(Throwable cause) {
return new FileUploadClient() {
@Override
public String fileUpload(MultipartFile file) {
if (cause instanceof BadRequestException) {
return "Bad Request!!!";
}
if (cause instanceof NotFoundException) {
return "Not Found!!!";
}
if (cause instanceof Exception) {
return "Exception!!!";
}
return "Successfully Uploaded file!!!";
}
};
}
}
Let’s now create a simple test to validate the FallbackFactory option:
现在让我们创建一个简单的测试来验证FallbackFactory选项。
@Test(expected = NotFoundException.class)
public void whenFileUploadClientFallbackFactory_thenFileUploadError() throws IOException {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
File file = new File(classloader.getResource(FILE_NAME).getFile());
Assert.assertTrue(file.exists());
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain",
IOUtils.toByteArray(input));
uploadService.uploadFileWithFallbackFactory(multipartFile);
}
6. Conclusion
6.结论
In this article, we’ve demonstrated how we can handle exceptions in feign.
在这篇文章中,我们已经演示了如何在feign中处理异常。
As always, all code samples used in this tutorial are available over on GitHub.
一如既往,本教程中使用的所有代码样本都可以在GitHub上找到。