Jetty 10迁移至Jetty 12:WebSocketServerComponents用法适配问题
Jetty 12(EE8)WebSocket迁移适配方案
针对你从Jetty 10(EE8)迁移到Jetty 12(EE8)时遇到的WebSocketServerComponents.ensureWebSocketComponents()用法问题,核心原因是Jetty 12对架构做了重大拆分——将EE规范实现(Servlet、WebSocket等)与Jetty核心服务器逻辑完全隔离,导致原有的Context API和组件初始化方式发生了变化,以下是具体的适配方案:
关键变化说明
- Context类迁移:原
org.eclipse.jetty.server.handler.ContextHandler.Context已迁移至EE8模块下的org.eclipse.jetty.ee8.nested.ContextHandler.APIContext,且不再暴露getServer()方法,这是为了隔离EE层与Jetty核心层的依赖,避免直接操作核心服务器对象。 - WebSocket组件包迁移:所有EE8相关的WebSocket类从
org.eclipse.jetty.websocket.server/servlet包迁移至org.eclipse.jetty.websocket.ee8.server/servlet包,必须调整导入路径才能兼容。
适配方案
1. 调整导入包
将原WebSocket相关导入替换为EE8模块下的类:
// 替换前 import org.eclipse.jetty.server.handler.ContextHandler.Context; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.websocket.server.JettyWebSocketCreator; import org.eclipse.jetty.websocket.server.JettyWebSocketServerContainer; import org.eclipse.jetty.websocket.server.JettyWebSocketServlet; import org.eclipse.jetty.websocket.server.JettyWebSocketServletFactory; import org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter; // 替换后 import org.eclipse.jetty.ee8.servlet.ServletContextHandler; import org.eclipse.jetty.websocket.ee8.server.JettyWebSocketCreator; import org.eclipse.jetty.websocket.ee8.server.JettyWebSocketServerContainer; import org.eclipse.jetty.websocket.ee8.server.JettyWebSocketServlet; import org.eclipse.jetty.websocket.ee8.server.JettyWebSocketServletFactory; import org.eclipse.jetty.websocket.ee8.servlet.WebSocketUpgradeFilter;
2. 修改WebSocket组件初始化逻辑
Jetty 12的WebSocketServerComponents提供了重载方法,无需传入Server对象,直接使用ServletContext即可完成组件初始化。同时JettyWebSocketServerContainer.ensureContainer()会自动触发依赖组件的初始化,可简化代码:
@Override public void init() throws ServletException { final ServletContext osgiServletContext = super.getServletContext().getContext("/"); context = ServletContextHandler.getServletContextHandler(osgiServletContext, "WebSockets"); JettyWebSocketServerContainer serverContainer = JettyWebSocketServerContainer.getContainer(osgiServletContext); if (serverContainer == null) { // 无需传入Server,直接用ServletContext初始化核心组件 WebSocketServerComponents.ensureWebSocketComponents(osgiServletContext); WebSocketUpgradeFilter.ensureFilter(osgiServletContext); WebSocketMappings.ensureMappings(osgiServletContext); // 自动创建并初始化WebSocket容器 serverContainer = JettyWebSocketServerContainer.ensureContainer(osgiServletContext); } super.init(); }
最佳实践建议
虽然在Servlet的init()方法中初始化WebSocket组件仍然可行,但更符合Jetty 12架构设计的方式是:
- 在ServletContextListener中完成WebSocket组件的初始化,避免在Servlet内部直接操作容器级组件;
- 若使用Jetty的程序化配置(而非OSGi声明式),可在Server启动阶段通过
ServletContextHandler直接配置WebSocket组件,例如:ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); // 配置WebSocket容器 JettyWebSocketServerContainer container = JettyWebSocketServerContainer.ensureContainer(contextHandler.getServletContext()); container.addEndpoint(MyWebSocketEndpoint.class);
注意事项
- 确保OSGi环境中已正确安装并激活Jetty的
jetty-ee8-websocket-server、jetty-ee8-servlet等模块; - 避免尝试通过反射或其他方式获取Jetty核心Server对象,这会破坏EE层与核心层的隔离设计,导致后续版本兼容性问题。
内容的提问来源于stack exchange,提问作者langri
相关产品推荐
相关产品推荐

