Java EE7 websocket 初始化 - 在第一个 @OnOpen 之前实现逻辑
Posted
技术标签:
【中文标题】Java EE7 websocket 初始化 - 在第一个 @OnOpen 之前实现逻辑【英文标题】:Java EE7 websocket initialization - implement logic before first @OnOpen 【发布时间】:2014-05-05 10:09:22 【问题描述】:我认为这更像是一个设计特定的问题,而不是直接编码问题。
我想实现一个 websocket 服务,该服务将来自外部 http:// 资源的更新数据集提供给客户端。
但我想在第一个客户端连接之前有可用的数据,所以@OnLoad
表示法不行。
在HttpServlet
世界我会
@Override
public void init() throws...
仅使用JSR-356,我无法找到合适的方法。
我尝试使用自定义ServerEndpointConfig.Configurator
,但这似乎无法让我从HttpServlet
访问类似于init()
的方法。
所以我的问题是:
让 websocket Endpoint 类扩展 HttpServlet
让我可以访问 init()
方法,我可以在那里放置我的初始逻辑。
这是解决我的问题的合适方法,还是我错过了 JSR-356 中的一些东西,它可以优雅地完成这项工作,而无需导入大部分未使用的 servlet 包?
非常感谢!
【问题讨论】:
【参考方案1】:每次通过@OnOpen
创建新连接时,都会实例化一个带有@ServerEndpoint("/myEndPoint")
注释的类。它既不是 static
类也不是单例(例如,不像 Spring @Service
那样表现)。
我有一个与你类似的问题,我需要让一个 Web 套接字成为 Spring Web 服务的观察者(不要问,我和你一样,这是一个糟糕的架构问题)。为了使其成为观察者,我必须将其添加到可观察类中,但由于缺少网络套接字的初始化,我没有明确的位置添加观察者,将其添加到 @987654326 @ 方法会在每个新连接上重复添加它。
我找到的唯一解决方案是一种变通方法。通常一个网络套接字类有一个static Set
连接到它的对等点,你需要类似的东西来初始化。在构造函数中使用static block
或static
标志。就我而言,我解决了:
private static boolean observerFlag = false;
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
public MyWebSocket()
if (!observerFlag)
observable.addObserver(this);
observerFlag = true;
并移除观察者:
@OnClose
public void onClose(Session peer)
peers.remove(peer);
if (peers.isEmpty())
observable.deleteObserver(this);
observerFlag = false;
我重申这是一种解决方法,我认为有一个更优雅的解决方案。
【讨论】:
至少 2 个同步错误:如果前几个请求发生的距离足够近,它可能会注册多次。同样在onClose
中,可能会在isEmpty()
调用之后立即添加一个新对等点,因此存在竞争条件。最简单的解决方法是将这些静态字段的所有访问和修改包装在块synchronized
上的某个用作锁的新对象上。使用synchronizedSet
是不够的,因为isEmpty
谓词随后没有被锁定;经典的先检查后行动比赛。以上是关于Java EE7 websocket 初始化 - 在第一个 @OnOpen 之前实现逻辑的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Jax-RS(Jersey) 在 Tomcat7 上运行应用程序 Hibernate 5.x、Jpa 2.1、Java EE7(javaee-api 7.0)
如何使用 Tyrus java 客户端在初始 WebSocket 客户端请求中包含 cookie?
Error information: “Error: SignerSign() failed.“ (-2147012889/0x80072ee7)