1. 概述
在本教程中,我們將演示如何在 Feign 中處理異常。Feign 是微服務開發人員的強大工具,並支持 ErrorDecoder 和 FallbackFactory 用於異常處理。
2. Maven 依賴
首先,讓我們通過包含 spring-cloud-starter-openfeign 創建一個 Spring Boot 項目。spring-cloud-starter-openfeign 包含其中的 feign-core 依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.3</version>
</dependency>我們也可以將 feign-core 依賴添加到我們的 pom.xml 文件中:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>11.9.1</version>
</dependency>3. 使用 ErrorDecoder 進行異常處理
我們可以通過配置 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);
}
}
}
在上述編碼器中,我們覆蓋了默認行為,從而獲得對異常的更多控制。
4. 使用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);
}
現在,讓我們創建一個名為 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!!!";
}
}
}
現在我們來創建一個簡單的測試,以驗證 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. 使用 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);
}現在,讓我們創建一個 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!!!";
}
};
}
}現在,讓我們創建一個簡單的測試,以驗證 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. 結論
在本文中,我們展示瞭如何處理Feign中的異常情況。