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 blockstatic 标志。就我而言,我解决了:

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?

怎么用netty搭建一个websocket的java客户端

Error information: “Error: SignerSign() failed.“ (-2147012889/0x80072ee7)

J2EE7与Servlet3.x

java怎么做websocket