案例研究:HTTP 請求函式和處理器

工程 | David Turanski | 2020 年 8 月 17 日 | ...

簡介

我們以介紹基於 Java 函式的新流應用程式函式組合來開始本系列。之前的文章提供了一個構建簡單流應用程式並在 Spring Cloud Data Flow 中執行的教程。今天,我們將探討 HTTP 請求函式,並提供如何使用它的示例。

如果您錯過了,本系列之前的文章有:

HTTP 請求函式

這是傳統 HTTP 客戶端處理器 流應用啟動器的一個更新實現,基於響應式 Spring WebClient。該函式是一個通用 Web 客戶端,它向 URL 提交 HTTP 請求並返回響應。它主要為流式應用程式設計,能夠使用針對每個傳入訊息評估的配置 SpEL 表示式 來提取 URL、HTTP 方法、請求體、所需的響應型別和內容。此外,為了支援高效的流處理,該函式使用響應式流。其簽名是

Function<Flux<Message>, Flux>

也就是說,它接受一個 Flux(訊息流)並返回一個任意型別的 Flux。

配置屬性

HttpRequestFunction 透過以下 配置屬性 進行配置

http.request.body-expression
一個 SpEL 表示式,用於從傳入訊息中派生請求體。(表示式,預設)

http.request.expected-response-type
用於解釋響應的型別。(Class<?>,預設值:String)

http.request.headers-expression
一個 SpEL 表示式,用於派生要使用的 http 頭對映。(表示式,預設)

http.request.http-method-expression
一個 SpEL 表示式,用於從傳入訊息中派生請求方法。(表示式,預設值:GET)

http.request.maximum-buffer-size
為輸入流緩衝區分配的最大緩衝區大小(以位元組為單位)。預設為 256k。如有必要,可增加此值以釋出或獲取大型二進位制內容。(Integer,預設值:256 * 1024)

http.request.reply-expression
一個 SpEL 表示式,用於計算最終結果,應用於整個 http {@link org.springframework.http.ResponseEntity}。(表示式,預設值:ResponseEntity::getBody)

http.request.timeout
請求超時(毫秒)。(Long,預設值:30000)

http.request.url-expression
一個針對傳入訊息的 SpEL 表示式,用於確定要使用的 URL。(表示式,預設)

SpEL 表示式應用於傳入的訊息。因此,像 bodyheaders[name] 這樣的欄位可以用來評估訊息內容。我說“可以…”是因為有時使用靜態值更可取。在這種情況下,字面值必須用單引號括起來,例如

http.request.url-expression='https://start.spring.io' http.request.http-method-expression='POST'

示例 1:在獨立應用程式中使用 HTTP 請求函式

讓我們看一個如何在簡單的 Spring Boot Web 應用程式中使用此函式的示例。在此示例中,我們將在一個從 URL 檢索影像並渲染影像縮圖的應用程式中使用它。此示例的完整程式碼位於此處

我們將使用 Spring Boot 和 Spring Web Flux 構建應用程式,以及我們的函式來檢索影像,以及一些用於生成縮圖的程式碼。

相關的依賴項是

  • org.springframework.cloud.fn:http-request-function - HTTP 請求函式間接包含 spring-boot-starter-webflux

  • io.spring.example:image-thumbnail-processor - 一個簡單的 Java 函式,包含在此示例中,用於建立縮圖。我們在此不深入討論細節,只需注意它是一個單獨的元件,我們將在後面的示例中重複使用。

我們首先需要為我們的函式設定一些配置屬性

http.request.url-expression=payload http.request.expected-response-type=byte[] http.request.maximum-buffer-size=2097152

因此,訊息有效負載包含目標 URL,影像(響應體)將作為位元組陣列返回。由於這些影像可能相當大,我們將響應體緩衝區的最大大小增加到 2GB (2 * 1024 * 1024)。

這是程式碼

@SpringBootApplication
@Controller
@Import(HttpRequestFunctionConfiguration.class)
public class ThumbnailStandaloneApplication {
  private static Logger logger = LoggerFactory.getLogger(ThumbnailStandaloneApplication.class);

  public static void main(String[] args) {
    SpringApplication.run(ThumbnailStandaloneApplication.class, args);
  }

  private ThumbnailProcessor thumbnailProcessor = new ThumbnailProcessor();

  @Autowired
  private HttpRequestFunction httpRequestFunction;

  @Bean
  RouterFunction<?> routes() {
    return RouterFunctions.route()
        .GET("/thumbnail", this::createThumbnail)
        .build();
  }

  private Mono<ServerResponse> createThumbnail(ServerRequest serverRequest) {
    String url = serverRequest.queryParam("url").orElseThrow(
                           () -> new RuntimeException("URL required"));

    return Mono.from(httpRequestFunction.apply(Flux.just(new GenericMessage<>(url)))
        .flatMap(image -> {
          Map<String, Object> model = new HashMap<>();
          byte[] thumbnail = thumbnailProcessor.apply((byte[]) image);
          logger.info("creating thumbnail for {}", url);
          model.put("url", url);
          model.put("thumb", new String(Base64.getEncoder().encode(thumbnail)));
          Mono<ServerResponse> serverResponse = ServerResponse.ok()
              .render("thumbnail", model);
          return serverResponse;
        }));
  }

我們應用 HttpRequestFunction 來檢索影像。然後我們將 thumbnailProcessor 應用於返回的位元組陣列,並將其編碼為 base 64,以便我們可以在頁面上渲染它。

standalone

示例 2:在流式應用程式中使用 HTTP 請求處理器

現在我們已經瞭解了我們的函式是如何工作的,讓我們使用 Spring Cloud Stream 組建一個流式應用程式,來做類似的事情。在這種情況下,我們將使用預打包的 HTTP 請求處理器檔案源 流應用程式。這個處理器將 HTTP 請求函式封裝在一個 Spring Cloud Stream 處理器應用程式中,該應用程式簡單地呼叫函式,將輸入和輸出繫結到訊息代理目標(例如,Kafka 主題或 Rabbit MQ 交換機)。我們的應用程式,以流定義 DSL 表示,看起來像

file-source | http-request-processor | image-thumbnail-sink

其中 | 表示使用訊息代理進行 I/O。

在這裡,我們正在使用一個 使用者開發的接收器,該接收器使用 檔案消費者 函式將每個縮圖寫入檔案。該接收器使用 Spring Cloud Function 的宣告式組合,將來自上一個示例的 縮圖處理器 與一個頭部豐富器組合起來,最後是標準的 檔案消費者。所以我們的組合函式定義為

spring.cloud.function.definition=thumbnailProcessor|filenameEnricher|fileConsumer

application.properties 中。

我們的複合函式定義在概念上和語法上與上述流定義相似。但在這裡,| 表示程序內通訊。

我們將在未來的文章中探討檔案源的方方面面。目前,我們將使用它來輪詢源目錄並在新檔案新增到目錄時生成訊息。在這種情況下,我們希望處理一個文字檔案,其中每行包含一個影像 URL。我們將配置源以每行生成一個訊息,其中有效負載中包含 URL。我們已經知道 HTTP 請求處理器做了什麼。接收器生成一個縮圖並將其寫入檔案。

完全配置的流定義是

file-source --file.consumer.mode=lines --file.consumer.mode=lines --file.supplier.directory=| http-request-processor --http.request.url-expression=payload --http.request.expected-response-type=byte[] --http.request.maximum-buffer-size=2097152| image-thumbnail-sink --file.consumer.directory=

如果執行此程式並將文字檔案放入源目錄,我們將看到縮圖寫入目標目錄

thumbnail files

如果您想在本地計算機上執行此程式,完整的說明請參閱此處

總結

我們剛剛深入探討了 HTTP 請求函式,演示瞭如何在獨立的 Web 應用程式和流處理管道中使用它來處理影像。我們還使用了函式組合,有效地組合了使用者編寫的函式和現成的函式。

敬請期待…​

在接下來的幾周,我們將展示更多關於 Spring Cloud Stream 和 Spring Cloud Data Flow 的案例研究,每個案例都將重點介紹不同的流應用程式和功能。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有