You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot+Tomcat9.0.14同时启用HTTP1.1与HTTP2的兼容问题

解决Spring Boot + Tomcat 9同时支持HTTP/2和HTTP/1.1的问题

看起来你的核心问题是已经在Spring Boot应用中启用了HTTP/2 over SSL,但HTTP/1.1客户端请求时出现连接异常,服务器无法正常响应。这是Tomcat配置HTTP/2时常见的小坑,下面一步步帮你解决:

一、确认核心配置的完整性

首先确保application.properties里同时配置完整的SSL参数和HTTP/2启用开关,这是双协议兼容的基础:

# SSL基础配置(替换为你的证书信息)
server.port=8443
server.ssl.key-store=classpath:your-keystore.jks
server.ssl.key-store-password=your-password
server.ssl.key-store-type=JKS
server.ssl.key-alias=your-key-alias
server.ssl.enabled-protocols=TLSv1.2,TLSv1.3  # HTTP/2要求TLS 1.2及以上版本

# 启用HTTP/2
server.http2.enabled=true

注意:HTTP/2 over TLS依赖ALPN(应用层协议协商),Java 9及以上版本已经内置ALPN支持,你当前的Java版本没问题,不需要额外依赖。

二、自定义Tomcat连接器强制双协议支持

虽然Spring Boot默认应该让Tomcat同时兼容HTTP/1.1和HTTP/2,但自动配置偶尔会有遗漏。我们可以显式自定义Tomcat连接器,确保双协议都能被处理:

创建一个Spring配置类:

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class TomcatHttp2Config implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers((Connector connector) -> {
            Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
            // 显式启用HTTP/2支持
            protocol.setHttp2(true);
            // 限定SSL协议版本为HTTP/2兼容的类型
            protocol.setSslEnabledProtocols("TLSv1.2,TLSv1.3");
            // 指定连接器为NIO类型,同时支持HTTP/1.1和HTTP/2
            connector.setProtocol("org.apache.coyote.http11.Http11NioProtocol");
        });
    }
}

这个配置会强制Tomcat的NIO连接器通过ALPN自动协商客户端支持的协议版本,同时处理HTTP/1.1和HTTP/2请求。

三、排查客户端侧的配置问题

如果服务器配置没问题,但客户端仍报错,可能是客户端本身的配置问题:

1. Java 9 HTTP/1.1客户端

如果服务器用的是自签名证书,HTTP/2客户端可能已经信任了证书,但HTTP/1.1客户端没配置信任逻辑。可以添加临时信任配置(仅测试环境使用,生产环境请用合法证书):

// 创建信任所有证书的SSL上下文(测试用)
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) {}
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) {}
    @Override
    public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}}, new SecureRandom());

// 构建HTTP/1.1客户端
HttpClient httpClient = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .sslContext(sslContext)
        .build();

2. Apache HttpClient 4.5.x

Apache HttpClient默认使用HTTP/1.1,但Expect: 100-continue请求头可能导致服务器无响应,可以关闭这个配置:

// 配置请求参数,关闭Expect:100-continue
RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(5000)
        .setSocketTimeout(5000)
        .setExpectContinueEnabled(false)
        .build();

// 构建HttpClient
CloseableHttpClient httpclient = HttpClients.custom()
        .setDefaultRequestConfig(requestConfig)
        .setConnectionManager(pool)
        .build();

四、验证配置是否生效

重启Spring Boot应用后,用以下方式验证双协议支持:

  • 测试HTTP/1.1:curl -v --http1.1 https://localhost:8443/your-endpoint
  • 测试HTTP/2:curl -v --http2 https://localhost:8443/your-endpoint

如果两者都能正常返回响应,说明配置成功了。

内容的提问来源于stack exchange,提问作者Sanjeev

火山引擎 最新活动