1. 概述
在本教程中,我們將演示如何使用 Open Feign 上傳文件。Feign 是一種強大的工具,微服務開發者可以使用它以聲明式的方式通過 REST API 與其他微服務進行通信。
2. 先決條件
假設已經暴露了一個 RESTful Web 服務,用於文件上傳,以下是詳細信息:
POST http://localhost:8081/upload-file因此,要解釋通過 Feign 客户端上傳文件,我們將暴露的 Web 服務 API 如下所示:
@PostMapping(value = "/upload-file")
public String handleFileUpload(@RequestPart(value = "file") MultipartFile file) {
// File upload logic
}3. 依賴
為了支持文件上傳時使用 application/x-www-form-urlencoded 和 multipart/form-data 編碼類型,我們需要 feign-core、feign-form 和 feign-form-spring 模塊。
因此,我們將向 Maven 添加以下依賴項:
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
<version>10.12</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.8.0</version>
</dependency>我們還可以使用 spring-cloud-starter-openfeign,它內部包含了 feign-core:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.0</version>
</dependency>4. 配置
請在主類中添加 @EnableFeignClients。 欲瞭解更多詳情,請參閲 spring cloud open feign 教程。
@SpringBootApplication
@EnableFeignClients
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}@EnableFeignClients 註解允許對聲明為Feign客户端的接口進行組件掃描。
5. 通過 Feign 客户端上傳文件
5.1. 通過標註的客户端
讓我們為標註的 @FeignClient 類創建所需的編碼器:
public class FeignSupportConfig {
@Bean
public Encoder multipartFormEncoder() {
return new SpringFormEncoder(new SpringEncoder(new ObjectFactory<HttpMessageConverters>() {
@Override
public HttpMessageConverters getObject() throws BeansException {
return new HttpMessageConverters(new RestTemplate().getMessageConverters());
}
}));
}
}請注意,FeignSupportConfig 不需要使用 @Configuration 註解。
現在,讓我們創建一個接口並使用 @FeignClient 註解對其進行標註。 此外,我們還將添加 name 和 configuration 屬性,並指定其對應的值。
@FeignClient(name = "file", url = "http://localhost:8081", configuration = FeignSupportConfig.class)
public interface UploadClient {
@PostMapping(value = "/upload-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
String fileUpload(@RequestPart(value = "file") MultipartFile file);
}
UploadClient 指向 the prerequisite 中提到的 API。
在與 Hystrix 協作時,我們將使用 fallback 屬性作為備用方案。 這在上傳 API 失敗時執行。
現在,我們的 @FeignClient 將如下所示:
@FeignClient(name = "file", url = "http://localhost:8081", fallback = UploadFallback.class, configuration = FeignSupportConfig.class)最後,我們可以直接從服務層調用 UploadClient:
public String uploadFile(MultipartFile file) {
return client.fileUpload(file);
}5.2. 通過 Feign.builder
在某些情況下,我們的 Feign 客户端需要進行自定義,這無法通過上述註解方式實現。在這種情況下,我們使用 Feign.builder() API 創建客户端。
下面我們創建一個包含針對 REST API 文件上傳方法的代理接口:
public interface UploadResource {
@RequestLine("POST /upload-file")
@Headers("Content-Type: multipart/form-data")
Response uploadFile(@Param("file") MultipartFile file);
}標註 @RequestLine 定義了 API 的 HTTP 方法和相對資源路徑,而 @Headers 則指定了諸如 Content-Type 等請求頭。
現在,讓我們在代理接口中調用指定的該方法。我們將從我們的服務類中執行此操作:
public boolean uploadFileWithManualClient(MultipartFile file) {
UploadResource fileUploadResource = Feign.builder().encoder(new SpringFormEncoder())
.target(UploadResource.class, HTTP_FILE_UPLOAD_URL);
Response response = fileUploadResource.uploadFile(file);
return response.status() == 200;
}在這裏,我們使用了 Feign.builder() 工具構建了 UploadResource 代理接口的一個實例。我們還使用了 SpringFormEncoder 以及基於 RESTful Web Service 的 URL。
6. 驗證
讓我們創建一個測試,以使用註釋的客户端驗證文件上傳。
@SpringBootTest
public class OpenFeignFileUploadLiveTest {
@Autowired
private UploadService uploadService;
private static String FILE_NAME = "fileupload.txt";
@Test
public void whenAnnotatedFeignClient_thenFileUploadSuccess() {
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));
String uploadFile = uploadService.uploadFile(multipartFile);
Assert.assertNotNull(uploadFile);
}
}現在,讓我們創建一個測試,以使用 Feign.Builder() 驗證文件上傳:
@Test
public void whenFeignBuilder_thenFileUploadSuccess() throws IOException {
// same as above
Assert.assertTrue(uploadService.uploadFileWithManualClient(multipartFile));
}7. 結論
在本文中,我們展示瞭如何使用 OpenFeign 實現 Multipart 文件上傳,以及如何在簡單應用程序中將其應用。
我們還了解到如何配置 Feign 客户端或使用 Feign.Builder() 以執行相同的操作。