Spring Boot 2.0.0 RC2嵌入Jetty启用HTTP/2遇阻求助
咱们先理清楚核心问题:你遇到的PRI帧日志、HTTP/2未生效的情况,大概率是因为Spring Boot 2.0早期版本(RC2)的Jetty HTTP/2支持需要满足几个关键前提,下面一步步给你拆解解决:
1. 补全HTTP/2必需的依赖
Spring Boot 2.0.0 RC2的spring-boot-starter-jetty默认没有包含HTTP/2相关的Jetty组件,你需要在pom.xml里手动添加以下依赖:
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-alpn-openjdk8-server</artifactId> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-http2-server</artifactId> </dependency>
其中ALPN(应用层协议协商)是HTTP/2 over TLS的核心组件,Jetty靠它和客户端协商使用HTTP/2协议。
2. 必须配置HTTPS(默认HTTP/2依赖TLS)
Jetty默认只支持h2协议(HTTP/2 over TLS),明文的h2c(无加密HTTP/2)需要额外特殊配置,且几乎不推荐生产环境使用。所以你得在application.properties里配置SSL证书:
# 启用HTTPS server.ssl.enabled=true # 密钥库路径(可以用自签名证书测试) server.ssl.key-store=classpath:keystore.jks # 密钥库密码 server.ssl.key-store-password=your-password # 密钥别名 server.ssl.key-alias=your-alias
如果没有现成证书,可以用Java的keytool生成自签名证书用于测试:
keytool -genkeypair -alias myjettycert -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore keystore.p12 -validity 3650
生成后把证书文件放到src/main/resources下,再对应调整application.properties里的路径和密码即可。
3. 用正确的cURL命令验证
测试HTTP/2需要用支持HTTP/2的cURL版本(建议7.47以上),并且加上对应参数:
# 自签名证书需要加--insecure跳过证书校验 curl -v --http2 --insecure https://localhost:8443/your-api-endpoint
如果输出里出现ALPN, offering h2和Using HTTP2, server supports multi-use的字样,就说明HTTP/2已经生效了。
4. 明文h2c的配置(仅用于测试场景)
如果确实需要无加密的HTTP/2(仅限本地测试),你需要自定义Jetty的连接工厂配置,创建一个配置类:
import org.eclipse.jetty.http2.server.HTTP2CServerConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JettyHttp2cConfig { @Bean public JettyServerCustomizer jettyServerCustomizer() { return server -> { HttpConfiguration httpConfig = new HttpConfiguration(); // 配置明文HTTP/2连接工厂 HTTP2CServerConnectionFactory h2cFactory = new HTTP2CServerConnectionFactory(httpConfig); HttpConnectionFactory http1Factory = new HttpConnectionFactory(httpConfig); server.setConnectionFactories(new ConnectionFactory[]{h2cFactory, http1Factory}); }; } }
测试时用--http2-prior-knowledge参数跳过协议协商:
curl -v --http2-prior-knowledge http://localhost:8080/your-api-endpoint
关于你看到的PRI帧日志
PRI是HTTP/2的连接前置请求帧,当客户端尝试发起HTTP/2连接,但服务器没正确配置ALPN或HTTPS时,Jetty会把这个请求判定为无效,最终降级用HTTP/1.1处理,所以你会在控制台看到PRI日志,但实际还是HTTP/1.1服务。
内容的提问来源于stack exchange,提问作者Random Guy

