嵌入式Tomcat 8.5.95中ServerContainer为空,WebSocket无法使用
解决嵌入式Tomcat 8.5获取ServerContainer为null的问题
核心原因
嵌入式Tomcat默认不会自动注册WebSocket相关的初始化器(WsSci),导致ServletContext中无法通过javax.websocket.server.ServerContainer属性获取到实例,必须手动触发WebSocket容器的初始化流程。
解决方案
方法1:手动注册Tomcat的WebSocket初始化器WsSci
在创建Tomcat上下文后,手动添加org.apache.tomcat.websocket.server.WsSci作为ServletContainerInitializer,这个类会负责初始化ServerContainer并将其绑定到ServletContext中。
修改你的main方法:
public static void main(String[] args) throws Exception { Tomcat tomcat = new Tomcat(); tomcat.setPort(8080); // 保持你原有上下文配置 var ctx = tomcat.addWebapp("", new File(".").getAbsolutePath()); // 关键步骤:添加Tomcat自带的WebSocket初始化器WsSci ctx.addServletContainerInitializer(new org.apache.tomcat.websocket.server.WsSci(), null); // 再添加自定义初始化器 ctx.addServletContainerInitializer(new Init(), null); // 原有HTTP Servlet配置 Tomcat.addServlet(ctx, "tunnel", new DummyGuacamoleTunnelServlet()); ctx.addServletMappingDecoded("/tunnel", "tunnel"); tomcat.start(); tomcat.getServer().await(); }
方法2:直接通过Tomcat API获取并初始化ServerContainer
如果方法1不生效,可以绕过ServletContext的自动绑定逻辑,手动创建并绑定WebSocket容器实例:
// 在main方法中、tomcat.start()之前执行 org.apache.tomcat.websocket.server.WsServerContainer container = (org.apache.tomcat.websocket.server.WsServerContainer) ctx.getServletContext().getAttribute( org.apache.tomcat.websocket.server.WsServerContainer.class.getName() ); // 若容器未初始化,则手动创建并绑定 if (container == null) { container = new org.apache.tomcat.websocket.server.WsServerContainer(ctx.getServletContext()); ctx.getServletContext().setAttribute( javax.websocket.server.ServerContainer.class.getName(), container ); } // 注册你的WebSocket端点 ServerEndpointConfig config = ServerEndpointConfig.Builder.create( DummyGuacamoleWebsocketEndpoint.class, "/websocket-tunnel") .subprotocols(Arrays.asList("guacamole")) .build(); container.addEndpoint(config);
依赖优化
移除重复的WebSocket API依赖,确保版本一致性:
dependencies { implementation("org.apache.guacamole:guacamole-common:1.5.3") implementation("org.apache.tomcat.embed:tomcat-embed-core:8.5.95") implementation("org.apache.tomcat.embed:tomcat-embed-websocket:8.5.95") compileOnly("javax.websocket:javax.websocket-api:1.1") }
验证修改
完成上述调整后启动应用,Init类中的ServerContainer将能正常获取实例,WebSocket端点可成功注册并工作。
内容的提问来源于stack exchange,提问作者Arikael
相关产品推荐
相关产品推荐

