我认为这更像是一个设计特定的问题,而不是直接编码问题。
我想实现一个websocket服务,该服务提供从外部http://资源到客户端的更新数据集。
但我想在第一个客户端连接之前获得数据,因此@OnLoad
表示法不会这样做。
在HttpServlet
世界,我会
@Override
public void init() throws...
我只是使用JSR-356找不到合适的方法。
我尝试使用自定义ServerEndpointConfig.Configurator
,但似乎无法访问init()
中与HttpServlet
类似的方法。
所以我的问题是:
让websocket Endpoint类扩展HttpServlet
使我能够访问init()
方法,并且可以将初始逻辑放在那里。
这是解决我的问题的合适方式,还是我错过了JSR-356中的一些优点,而且没有导入大部分未使用的servlet包?
非常感谢!
答案 0 :(得分:3)
每次通过@ServerEndpoint("/myEndPoint")
创建新连接时,都会实例化注释为@OnOpen
的类。它不是static
类,也不是单例(例如,不像Spring @Service
)。
我遇到了类似的问题,我需要将一个Web套件作为Spring Web服务的观察者(不要问,我和你在一起这是一个糟糕的架构问题)。为了使它成为一个观察者,我必须将它添加到可观察的类中,但是由于缺少web插座的初始化,我没有明确的位置添加观察者,将其添加到@OnOpen
方法会在每个新连接上重复添加它。
我找到的唯一解决方案是解决方法。通常,Web套接字类具有连接到它的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;
}
}
我重申这是一种解决方法,我认为有更优雅的解决方案。