gpt4 book ai didi

websocket - 从 Web Socket @ServerEndpoint 中的 HttpServletRequest 访问 HttpSession

转载 作者:行者123 更新时间:2023-12-03 01:57:35 25 4
gpt4 key购买 nike

是否可以在@ServerEndpoint 中获取 HttpServletRequest?主要是我试图获取它以便我可以访问 HttpSession 对象。

最佳答案

Update (November 2016): The information provided in this answer is for the JSR356 spec, individual implementations of the spec may vary outside of this information. Other suggestions found in comments and other answers are all implementation specific behaviors outside of the JSR356 spec.

If the suggestions in here are causing you problems, upgrade your various installations of Jetty, Tomcat, Wildfly, or Glassfish/Tyrus. All current versions of those implementations have all been reported to work in the way outlined below.


现在回到 的原始答案2013 年 8 月 ...
Martin Andersson 的回答存在并发缺陷。 Configurator 可以被多个线程同时调用,很可能在来自 modifyHandshake() 的调用之间您将无法访问正确的 HttpSession 对象。和 getEndpointInstance() .
或者换一种说法...
  • 请求 A
  • 修改握手A
  • 请求 B
  • 修改握手B
  • 获取端点实例 A <-- 这将具有请求 B 的 HttpSession
  • 获取端点实例 B

  • 这是对使用 ServerEndpointConfig.getUserProperties() 的 Martin 代码的修改。 map 制作 HttpSession@OnOpen 期间可用于您的套接字实例方法调用
    GetHttpSessionConfigurator.java
    package examples;

    import javax.servlet.http.HttpSession;
    import javax.websocket.HandshakeResponse;
    import javax.websocket.server.HandshakeRequest;
    import javax.websocket.server.ServerEndpointConfig;

    public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator
    {
    @Override
    public void modifyHandshake(ServerEndpointConfig config,
    HandshakeRequest request,
    HandshakeResponse response)
    {
    HttpSession httpSession = (HttpSession)request.getHttpSession();
    config.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
    }
    GetHttpSessionSocket.java
    package examples;

    import java.io.IOException;

    import javax.servlet.http.HttpSession;
    import javax.websocket.EndpointConfig;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;

    @ServerEndpoint(value = "/example",
    configurator = GetHttpSessionConfigurator.class)
    public class GetHttpSessionSocket
    {
    private Session wsSession;
    private HttpSession httpSession;

    @OnOpen
    public void open(Session session, EndpointConfig config) {
    this.wsSession = session;
    this.httpSession = (HttpSession) config.getUserProperties()
    .get(HttpSession.class.getName());
    }

    @OnMessage
    public void echo(String msg) throws IOException {
    wsSession.getBasicRemote().sendText(msg);
    }
    }
    奖励功能:无 instanceof或需要类型转换。
    一些 EndpointConfig 知识 EndpointConfig每个“端点实例”确实存在对象。
    但是,“端点实例”在规范中有两种含义。
  • JSR 的默认行为,其中每个传入的升级请求都会产生端点类的新对象实例
  • 一个 javax.websocket.Session它将对象端点实例及其配置与特定的逻辑连接联系在一起。

  • 可以将一个单例 Endpoint 实例用于多个 javax.websocket.Session实例(这是 ServerEndpointConfig.Configurator 支持的功能之一)
    ServerContainer 实现将跟踪一组 ServerEndpointConfig,它们代表服务器可以响应 websocket 升级请求的所有已部署端点。
    这些 ServerEndpointConfig 对象实例可以来自几个不同的来源。
  • javax.websocket.server.ServerContainer.addEndpoint(ServerEndpointConfig) 手动提供
  • 通常在 javax.servlet.ServletContextInitializer.contextInitialized(ServletContextEvent sce) 内完成调用

  • 来自 javax.websocket.server.ServerApplicationConfig.getEndpointConfigs(Set)称呼。
  • 通过扫描 Web 应用程序自动创建 @ServerEndpoint带注释的类。

  • 这些 ServerEndpointConfig对象实例作为 javax.websocket.Session 时的默认值存在最终会被创建。
    ServerEndpointConfig.Configurator 实例
    在接收或处理任何升级请求之前,所有 ServerEndpointConfig.Configurator对象现在存在并准备执行其主要和唯一目的,以允许自定义 websocket 连接到最终 javax.websocket.Session 的升级过程。
    访问特定于 session 的 EndpointConfig
    请注意,您无法访问 ServerEndpointConfig端点实例中的对象实例。您只能访问 EndpointConfig实例。
    这意味着如果您提供了 ServerContainer.addEndpoint(new MyCustomServerEndpointConfig())在部署期间,后来尝试通过注释访问它,它将不起作用。
    以下所有内容均无效。
    @OnOpen
    public void onOpen(Session session, EndpointConfig config)
    {
    MyCustomServerEndpointConfig myconfig = (MyCustomServerEndpointConfig) config;
    /* this would fail as the config is cannot be cast around like that */
    }

    // --- or ---

    @OnOpen
    public void onOpen(Session session, ServerEndpointConfig config)
    {
    /* For @OnOpen, the websocket implementation would assume
    that the ServerEndpointConfig to be a declared PathParam
    */
    }

    // --- or ---

    @OnOpen
    public void onOpen(Session session, MyCustomServerEndpointConfig config)
    {
    /* Again, for @OnOpen, the websocket implementation would assume
    that the MyCustomServerEndpointConfig to be a declared PathParam
    */
    }
    您可以在 Endpoint 对象实例的生命周期内访问 EndpointConfig,但在有限的时间内。 javax.websocket.Endpoint.onOpen(Session,Endpoint) , 注释 @OnOpen方法,或通过使用 CDI。 EndpointConfig 不能以任何其他方式或在任何其他时间使用。
    但是,您始终可以通过 Session.getUserProperties() 访问 UserProperties。电话,随时可用。此用户属性映射始终可用,无论是通过带注释的技术(例如 @OnOpen@OnClose@OnError@OnMessage 调用期间的 Session 参数),还是通过 session 的 CDI 注入(inject),甚至使用使用从 javax.websocket.Endpoint 扩展的非注释 websockets .
    升级的工作原理
    如前所述,每个定义的端点都会有一个 ServerEndpointConfig与之相关。
    那些 ServerEndpointConfigs是表示 EndpointConfig 的默认状态的单个实例最终可用于可能并最终创建的端点实例。
    当传入的升级请求到达时,它会在 JSR 上执行以下操作。
  • 路径是否匹配任何 ServerEndpointConfig.getPath() 条目
  • 如果不匹配,则返回 404 升级

  • 将升级请求传递到 ServerEndpointConfig.Configurator.checkOrigin()
  • 如果无效,返回错误升级响应
  • 创建握手响应

  • 将升级请求传递到 ServerEndpointConfig.Configurator.getNegotiatedSubprotocol()
  • 在 HandshakeResponse 中存储答案

  • 将升级请求传递到 ServerEndpointConfig.Configurator.getNegotiatedExtensions()
  • 在 HandshakeResponse 中存储答案

  • 创建新的端点特定的 ServerEndpointConfig 对象。复制编码器、解码器和用户属性。这个新的 ServerEndpointConfig 包装了路径、扩展、端点类、子协议(protocol)、配置器的默认值。
  • 将升级请求、响应和新的 ServerEndpointConfig 传递到 ServerEndpointConfig.Configurator.modifyHandshake()
  • 调用 ServerEndpointConfig.getEndpointClass()
  • 在 ServerEndpointConfig.Configurator.getEndpointInstance(Class) 上使用类
  • 创建 Session,关联端点实例和 EndpointConfig 对象。
  • 通知连接的端点实例
  • 需要 EndpointConfig 的带注释的方法获取与此 session 关联的方法。
  • 调用 Session.getUserProperties() 返回 EndpointConfig.getUserProperties()

  • 需要注意的是,ServerEndpointConfig.Configurator 是一个单独的,每个映射的 ServerContainer 端点。
    这是有意的,也是期望的,以允许实现者使用多种功能。
  • 如果他们愿意,可以为多个对等方返回相同的端点实例。所谓的无状态方法来编写 websocket。
  • 对所有端点实例的昂贵资源进行单点管理

  • 如果实现为每次握手创建了一个新的配置器,这种技术将是不可能的。
    (披露:我为 Jetty 9 编写和维护 JSR-356 实现)

    关于websocket - 从 Web Socket @ServerEndpoint 中的 HttpServletRequest 访问 HttpSession,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17936440/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com