如何用Apache CloseableHttpClient处理HTTP/2请求(遇505错误)
解决方案
关键依赖补充
首先确保项目中除了httpclient5,还引入HTTP/2支持的核心依赖,版本需与httpclient5保持一致(5.3.1):
<!-- Maven依赖示例 --> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.3.1</version> </dependency> <dependency> <groupId>org.apache.httpcomponents.core5</groupId> <artifactId>httpcore5-h2</artifactId> <version>5.3.1</version> </dependency>
正确配置CloseableHttpClient支持h2c
默认的CloseableHttpClient未启用HTTP/2协商和h2c升级逻辑,需手动配置连接管理器和版本策略:
import org.apache.hc.client5.http.classic.CloseableHttpClient; import org.apache.hc.client5.http.classic.methods.HttpGet; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; import org.apache.hc.core5.http.HttpVersion; import org.apache.hc.core5.http.config.Registry; import org.apache.hc.core5.http.config.RegistryBuilder; import org.apache.hc.core5.http.io.HttpClientConnectionOperator; import org.apache.hc.core5.http.io.SocketConfig; import org.apache.hc.core5.http.io.operators.DefaultHttpClientConnectionOperator; import org.apache.hc.core5.http2.HttpVersionPolicy; import org.apache.hc.core5.http2.config.H2Config; import org.apache.hc.core5.http2.impl.nio.DefaultHttp2ClientConnectionOperator; import org.apache.hc.core5.util.Timeout; public class H2cSyncClient { public static void main(String[] args) throws Exception { // 配置HTTP/2基础参数 H2Config h2Config = H2Config.custom() .setPushEnabled(false) .build(); // 注册HTTP/1.1和HTTP/2的连接处理器 Registry<HttpClientConnectionOperator> connOperatorRegistry = RegistryBuilder.<HttpClientConnectionOperator>create() .register(HttpVersion.HTTP_1_1, new DefaultHttpClientConnectionOperator()) .register(HttpVersion.HTTP_2, new DefaultHttp2ClientConnectionOperator(h2Config)) .build(); // 构建支持HTTP/2的连接管理器 PoolingHttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create() .setSocketConfig(SocketConfig.custom() .setSoTimeout(Timeout.ofSeconds(10)) .build()) .setConnectionOperatorRegistry(connOperatorRegistry) .build(); // 创建支持h2c升级的同步HttpClient try (CloseableHttpClient httpClient = HttpClients.custom() .setConnectionManager(connManager) .setVersionPolicy(HttpVersionPolicy.NEGOTIATE) // 允许协商HTTP版本,触发h2c升级 .build()) { HttpGet request = new HttpGet("http://192.168.0.171:20002"); // 手动添加升级头,确保服务器识别h2c请求(部分服务器需要明确触发) request.setHeader("Upgrade", "h2c"); request.setHeader("Connection", "Upgrade"); try (CloseableHttpResponse response = httpClient.execute(request)) { System.out.println("响应状态码: " + response.getCode()); System.out.println("使用HTTP版本: " + response.getVersion()); // 后续处理响应内容逻辑 } } } }
核心配置说明
- 依赖补充:
httpcore5-h2是HttpClient5支持HTTP/2的核心模块,缺失会导致无法处理HTTP/2连接逻辑。 - 连接管理器配置:注册HTTP/2的连接处理器
DefaultHttp2ClientConnectionOperator,让客户端具备处理HTTP/2连接的能力。 - 版本协商策略:
HttpVersionPolicy.NEGOTIATE会让客户端主动尝试通过Upgrade头升级到HTTP/2。 - 手动添加升级头:部分服务器需要明确的
Upgrade: h2c和Connection: Upgrade头才会触发h2c升级,手动添加可避免自动协商失效的情况。
排查要点
- 确认所有HTTP组件版本一致,避免版本不兼容导致的异常。
- 检查是否有请求拦截器或代理修改/移除了Upgrade相关请求头。
- 若服务器要求特定的h2c设置(如设置
HTTP2-Settings头),可在请求中添加:request.setHeader("HTTP2-Settings", "AAMAAABkAAQAAP__");(空设置值,符合规范)
内容的提问来源于stack exchange,提问作者dev_jongtae
相关产品推荐
相关产品推荐

