Jetty中WebSocketServlet无法读取HttpServlet设置的Session属性问题
问题根源分析
你遇到的核心问题是:两个独立的ServletContextHandler会维护各自独立的会话上下文。虽然你都开启了SESSIONS模式,但Jetty中每个ServletContextHandler默认会创建自己的SessionHandler和会话存储容器。这就导致HTTP请求和WebSocket请求看似使用同一个JSESSIONID Cookie,但实际对应的是两个完全隔离的会话对象——从你调试信息里的Session@24b04e4和Session@5989f3d1也能看出来,它们是不同的实例,自然共享不了属性。
解决方案
有两种靠谱的解决方式,任选其一即可:
方案1:给两个ServletContextHandler共用同一个SessionHandler
创建一个共享的SessionHandler实例,然后分别设置给HTTP和WebSocket的ServletContextHandler,让它们共用同一会话存储:
// 创建共享的SessionHandler val sharedSessionHandler = SessionHandler() // HTTP Handler配置 val httpHandler = object : ServletContextHandler(nullParent, contextPath, SESSIONS).apply { addServlet(ServletHolder(httpServlet), "/*") // 设置共享的SessionHandler sessionHandler = sharedSessionHandler } // WebSocket Handler配置 val webSocketHandler = object : ServletContextHandler(nullParent, contextPath, SESSIONS).apply { addServlet(ServletHolder(wsServlet), "/*") // 设置共享的SessionHandler sessionHandler = sharedSessionHandler } // 绑定到Server server.handler = HandlerList(httpHandler, webSocketHandler)
方案2:合并为同一个ServletContextHandler
把HTTP Servlet和WebSocket Servlet注册到同一个ServletContextHandler下,通过不同的路径映射区分请求,这样它们天然共享同一会话上下文:
val combinedHandler = ServletContextHandler(nullParent, contextPath, SESSIONS).apply { // HTTP请求映射到根路径 addServlet(ServletHolder(httpServlet), "/*") // WebSocket请求映射到/websocket路径 addServlet(ServletHolder(wsServlet), "/websocket") } // 直接绑定合并后的Handler到Server server.handler = combinedHandler
这种方式更简洁,也更符合Jetty的常规使用方式,推荐优先考虑。
补充说明
需要注意的是,如果你保留原来的HandlerList方式,一定要确保HTTP Handler在检测到WebSocket升级请求时正确返回,让请求流转到WebSocket Handler——不过方案2已经不需要这种判断了,因为路径映射会直接区分请求归属。
内容的提问来源于stack exchange,提问作者tipsy
相关产品推荐
相关产品推荐

