javax.websocket客户端WSS连接异常求助(Eclipse IDE+Jetty 9)
解决Jetty 9下javax.websocket客户端wss协议连接问题
我之前处理过Jetty 9结合javax.websocket客户端使用wss协议的场景,你的问题核心在于标准的WebSocket容器不会自动加载自定义SSL配置,得手动关联Jetty的SslContextFactory到客户端实例里。下面一步步给你解决:
核心思路
Jetty的javax.websocket实现依赖WebSocketClient来处理底层连接,我们需要先配置好支持SSL的SslContextFactory.Client,再把它绑定到WebSocketClient,最后通过Jetty的ClientContainer来创建JSR356标准的会话。
完整代码示例
import java.io.FileInputStream; import java.net.URI; import java.security.KeyStore; import javax.websocket.ClientEndpoint; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.jetty.websocket.jsr356.ClientContainer; @ClientEndpoint public class WssWebSocketClient { @OnOpen public void onSessionOpen(Session session) { System.out.println("成功建立wss连接:" + session.getRequestURI()); } @OnMessage public void onMessageReceived(String message) { System.out.println("收到服务器消息:" + message); } public static void main(String[] args) throws Exception { // 1. 配置SSL上下文工厂(客户端专用) SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); // 场景1:服务器使用自签名证书,加载自定义密钥库 KeyStore trustStore = KeyStore.getInstance("JKS"); try (FileInputStream fis = new FileInputStream("你的密钥库路径/truststore.jks")) { trustStore.load(fis, "密钥库密码".toCharArray()); } sslContextFactory.setTrustStore(trustStore); sslContextFactory.setTrustStorePassword("密钥库密码"); // 场景2:测试环境临时信任所有证书(生产环境绝对禁用!) // sslContextFactory.setTrustAll(true); // 2. 初始化Jetty WebSocket客户端 WebSocketClient jettyClient = new WebSocketClient(sslContextFactory); jettyClient.start(); // 3. 获取JSR356标准的客户端容器 ClientContainer clientContainer = ClientContainer.getContainer(jettyClient); // 4. 连接wss地址 URI wssUri = new URI("wss://你的服务器地址:端口/websocket路径"); Session session = clientContainer.connectToServer(WssWebSocketClient.class, wssUri); // 发送测试消息 session.getBasicRemote().sendText("Hello WSS Client!"); // 保持连接(按需调整,实际业务中可通过阻塞或监听事件处理) Thread.sleep(10000); // 关闭资源 session.close(); jettyClient.stop(); } }
关键细节说明
- 为什么不用标准ContainerProvider?:标准的
ContainerProvider.getWebSocketContainer()会创建默认容器,但不会自动应用我们的SSL配置,手动绑定Jetty的WebSocketClient才能确保SSL上下文生效。 - SSL配置的两种场景:
- 生产环境:必须加载信任库,只信任合法的服务器证书,避免安全风险。
- 测试环境:可以临时开启
setTrustAll(true),但上线前一定要删掉这个配置。
- 依赖检查:确保你的项目引入了Jetty 9的相关依赖,比如
jetty-websocket-client、jetty-util、jetty-websocket-jsr356,版本要统一。
常见问题排查
如果还是连接失败,可以试试这些方法:
- 开启Jetty的调试日志,查看SSL握手过程:
日志会告诉你具体的错误,比如证书不被信任、协议版本不兼容(Jetty 9默认支持TLS 1.2+,如果服务器用旧协议,可通过import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.StdErrLog; public static void main(String[] args) throws Exception { // 开启调试日志 StdErrLog debugLog = new StdErrLog(); debugLog.setLevel(StdErrLog.LEVEL_DEBUG); Log.setLog(debugLog); // 后续代码不变... }sslContextFactory.setIncludeProtocols("TLSv1.2")指定)。 - 检查服务器端的SSL端口是否开放,防火墙是否允许客户端访问。
- 确认wss地址的格式正确,比如
wss://domain:port/path,不要遗漏端口(默认443可以省略)。
内容的提问来源于stack exchange,提问作者Mikhail Stepanov
相关产品推荐
相关产品推荐

