1. 簡介
在本教程中,我們將探討如何發送包含壓縮數據的 HTTP 請求。
此外,我們還將探討如何配置 Spring Web 應用程序,使其處理壓縮請求。
2. 發送壓縮請求
首先,讓我們創建一個用於壓縮字節數組的方法。 這在稍後會派上用場:
public static byte[] compress(byte[] body) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
gzipOutputStream.write(body);
}
return baos.toByteArray();
}
接下來,我們需要實現一個 ClientHttpRequestInterceptor 以修改請求。 請注意,我們將同時發送適當的 HTTP 壓縮頭,並調用我們的字節數組壓縮方法:
public ClientHttpResponse intercept(HttpRequest req, byte[] body, ClientHttpRequestExecution exec)
throws IOException {
HttpHeaders httpHeaders = req.getHeaders();
httpHeaders.add(HttpHeaders.CONTENT_ENCODING, "gzip");
httpHeaders.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
return exec.execute(req, compress(body));
}
我們的攔截器將壓縮出站請求體,使用 GZIP 格式。 在此示例中,我們使用 Java 的標準 GZIPOutputStream 來完成工作。
此外,我們必須添加適當的數據編碼頭。 這可以讓目標端點知道它正在處理 GZIP 壓縮數據。
最後,我們將攔截器添加到我們的 RestTemplate 定義中:
@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new CompressingClientHttpRequestInterceptor());
return restTemplate;
}
3. 處理壓縮請求
默認情況下,大多數Web服務器不理解包含壓縮數據的請求。Spring Web應用程序也不例外。因此,我們需要配置它們來處理此類請求。
目前,僅 Jetty 和 Undertow Web 服務器能夠處理包含 GZIP 格式數據的請求主體。請參閲有關 Spring Boot 應用程序配置的文章,以設置 Jetty 或 Undertow Web 服務器。
3.1. Jetty Web 服務器
在此示例中,我們通過向 Jetty Web 服務器添加 GzipHandler 來自定義 Jetty Web 服務器。此 Jetty 處理程序旨在壓縮響應和解壓縮請求。
但是,添加它到 Jetty Web 服務器還不夠。我們需要將 inflateBufferSize 設置為一個大於零的值,以啓用解壓縮:
@Bean
public JettyServletWebServerFactory jettyServletWebServerFactory() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.addServerCustomizers(server -> {
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setInflateBufferSize(1);
gzipHandler.setHandler(server.getHandler());
HandlerCollection handlerCollection = new HandlerCollection(gzipHandler);
server.setHandler(handlerCollection);
});
return factory;
}
3.2. Undertow Web 服務器
同樣,我們可以自定義 Undertow Web 服務器,以便自動解壓縮請求。在這種情況下,我們需要添加一個自定義 RequestEncodingHandler。
我們配置編碼處理程序以處理來自請求的 GZIP 源數據:
@Bean
public UndertowServletWebServerFactory undertowServletWebServerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addDeploymentInfoCustomizers((deploymentInfo) -> {
deploymentInfo.addInitialHandlerChainWrapper(handler -> new RequestEncodingHandler(handler)
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER));
});
return factory;
}
4. 結論
這就是讓壓縮請求工作所需要做的全部!
在本教程中,我們學習瞭如何為 RestTemplate 創建攔截器,以壓縮請求的內容。我們還研究瞭如何在 Spring Web 應用程序中自動解壓縮這些請求。
重要的是,我們應該僅將壓縮內容發送到能夠處理此類請求的 Web 服務器。