我目前正在jetty上部署,但我想每个实现都遵循相同的概念。那么它是返回一个HashMap还是ConcurrentHashMap或者其他什么。我试图检查Jetty的WebsocketSession的实现源,但在内部我没有找到用映射初始化用户属性的位置。对于jetty,我可以使用调试器来检查将哪个用户属性实例分配给会话,但这并不能回答其他应用程序服务器是否也会这样做的问题。
有人知道答案吗?SearchWebSites大多返回关于websocket的教程,并且无法得到这个特定问题的答案
Tyrus实现
至于Tyrus,我看了一下TyrusSession.java
的实现。您感兴趣的摘录(数字指行):
87 public class TyrusSession implements Session, DistributedSession {
104 private final Map<String, Object> userProperties;
127 TyrusSession(...) {
191 userProperties = new HashMap<String, Object>();
192 }
... }
所以它是一个基本的HashMap。但是,您应该NOT依赖于实现。这就是为什么签名是由Map<String, Object>
定义的,而不是由ConcurrentHashMap
或任何复杂的东西定义的:
用户属性:
如JSR 359第2.1.2节所定义:
开发人员可以使用可通过Session对象上的getUserProperties()调用访问的用户属性映射,将特定于应用程序的信息与特定会话关联起来。websocket实现必须保留此会话数据以便以后访问,直到端点实例上的onClose()方法完成为止。[WSC 2.1.2-2]。在此之后,允许websocket实现丢弃开发人员数据。
JSR的强调
用户属性映射仅特定于给定的websocket会话,因此没有并发访问的意义。你可能有另一个涉及多个会话的对象,但那将是一个你自己的对象,所以你可以决定要使用什么。
一个会话=一个服务器端点实例
我想补充一点,您的服务器端点不是一个单例:每个对等端(会话)应有一个端点实例。来自JSR359的第5.1节:
除非有一个具有不同生命周期的Java EE组件支持(请参阅第7章),否则容器必须为每个对等点使用一个唯一的端点实例。[WSC-5.1-1]在任何情况下,实现都不得每次调用每个对等点有一个以上线程的端点实例。[WSC-5.1-2]在打开方法完成之前,实现可能不会在端点上调用关闭方法。[WSC-5.1-3]
这保证了每个对等点一次调用一个websocket端点实例的容器线程不会超过一个。[WSC-5.1-4]
简而言之,在websocket设计期间,当处理用户属性时,以及更全局地处理集合时:
- 一个会话有自己的实例或
@ServerEndPoint
- 不要假设websocket是线程安全的
- 只依赖规范,不依赖实现
关于javax.websocket.session
中用户属性的侧节点:
请注意,userProperties
只是实例化的,而不是从任何其他映射中填充的。我强调了这一点,以防您通过扩展ServerEndpointConfig.Configurator
使用自定义配置程序:如果您在ServerEndpointConfig.getUserProperties()
中放入一些数据,它们将不会自动复制到Session.getUserProperties()
中