【问题标题】:How to access "session" scoped beans in a Spring WebSocket handler (not "websocket" scope)如何在 Spring WebSocket 处理程序(不是“websocket”范围)中访问“会话”范围的 bean
【发布时间】:2017-05-09 01:12:43
【问题描述】:

在原始 Spring WebSocket 应用程序(不使用 sockjs/STOMP 或任何其他中间件)中,如何让 Spring 注入已在 HTTP 会话范围内注册的 bean,以便它们可以被我的 WebSocketHandler 中的代码使用豆子?

请注意,我不是要问的是以下任何一个问题:

  • 如何在同一 WebSocket 会话的所有处理程序调用都可以访问的范围内创建 bean(例如,如Request or Session scope in Spring Websocket 的答案中所述)。我需要访问的 bean 已经存在于 HTTP 会话的范围内
  • 我如何(以编程方式)访问 servlet 容器的 HTTP 会话存储中的对象(我没有尝试这样做,但我很确定答案涉及使用 HttpSessionHandshakeInterceptor),但这并没有我注入 Spring 范围的依赖项。
  • 如何使用 ScopedProxy 在不同范围内的代码之间传递 bean(例如,如 here 所述);我已经熟悉如何执行此操作,但尝试为 WebSocketHandler 执行此操作会导致错误,因为在访问对象时,session 范围尚未绑定到线程。
  • How to access the current security principal -- 再次强调,非常有用,但不是我目前想要达到的目标。

我希望做的是提供一个简单的框架,允许 MVC 应用程序的传统 HTTP 请求启动部分直接与 WebSocket 协议通信(用于向客户端发送简单的推送更新)。我想要做的是将数据从 MVC 控制器推送到会话范围的对象中,然后在 websocket 处理程序中将其拉出。 从 MVC 控制器的角度,我想要最简单的 API,如果可以只使用会话范围的 bean,那将是理想的。如果您对共享这些数据的非常简单的方法有任何其他想法,我也想听听这些想法,以防这种方法不可行。

【问题讨论】:

    标签: spring-mvc websocket


    【解决方案1】:

    您还可以将 Java API 用于 websocket。此链接https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support 解释了如何使用 Spring 执行此操作。 不幸的是,像这样的

    @ServerEndpoint(value = "/sample", configurator = SpringConfigurator.class)
    public class SampleEndpoint {
    
         private SessionScopedBean sessionScopedBean;
    
         @Autowired
          public SampleEndpoint(SessionScopedBean sessionScopedBean) {
            this.sessionScopedBean = sessionScopedBean;
          }
    }
    

    导致异常(因为我们试图在其范围之外访问 bean),但对于单例和原型 bean,它运行良好。

    要使用会话属性,您可以修改 hanshake 并传递所需的属性:

    public class CustomWebSocketConfigurator extends SpringConfigurator {
        @Override
        public void modifyHandshake(ServerEndpointConfig config,
                HandshakeRequest request,
                HandshakeResponse response) {
    
            //put attributes from http session to websocket session
            HttpSession httpSession = (HttpSession) request.getHttpSession();
            config.getUserProperties().put("some_attribute",
                   httpSession.getAttribute("some_attribute_in_http_session"));
        }
    }
    

    P。 S. 更多的是评论而不是答案。我只是想在您的问答中添加另一种在 websocket 中处理会话属性的方法。我一直在网上搜索完全相同的问题,上面显示的方式在我看来是处理 websocket 中会话数据的最系统的方法。

    【讨论】:

    • 不幸的是,这些建议实际上都不允许您将会话范围的 bean 用作 websocket 处理程序中的字段。第二个允许您以编程方式 获取它们,但对于可测试性而言,注入 bean 依赖项至关重要。不过,我确实有一个解决方案,当我完成它的工作时,我会写下来。不幸的是,这并不简单......
    • @Jules 我写过它不适用于会话范围。我认为这是因为 websocket 仅在握手时才知道上面的 http,所以这自然是您也没有被授予对会话范围 bean 的访问权限。我在我的项目中使用了这个解决方案,我只有一个 websocket 端点,所以我可以只在一个代码位置传递用户 ID,并使用服务层中非会话范围的 bean。我决定在此处发布此解决方案,即使它仅部分适用于发布的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 2012-01-20
    • 2012-10-31
    相关资源
    最近更新 更多