Android,iOS和桌面浏览器客户端目前每隔几秒钟轮询一次PHP后端(在CentOS Linux上使用PostgreSQL数据库)。
我想使用独立的Jetty Websocket Server替换轮询,以通知客户端,新数据可在后端获取。
因此,在自定义WebSocketListener
中,我对连接的客户端进行身份验证并将其存储在ConcurrentHashMap<String,Session>
中:
public class MyListener implements WebSocketListener
{
private Session mSession;
@Override
public void onWebSocketConnect(Session session) {
mSession = session;
}
@Override
public void onWebSocketText(String message) {
if (mSession != null && mSession.isOpen()) {
// 1. validate client id and password
// 2. store client id and session into Map
}
}
我的问题:如何通知连接的(通过websockets)客户端?
即。在PHP脚本中,我想运行一个轻量级程序java -jar MyNotify.jar client-1234
来告诉Jetty独立服务器:
嘿,数据库中有
client-1234
的新数据!请通过电话通过websockets发送短信
MyMap.get("client-1234").getRemote().sendString("hey", null);
答案 0 :(得分:0)
你必须把你的
ConcurrentHashMap<String,Session> sessionMap.
自定义javax.servlet.ServletContextEvent上的公共静态字段。应该在事件
上初始化字段 @Override
public void contextInitialized(ServletContextEvent ctx) {
然后在你的app中的任何地方,你都可以正常方式访问这个静态字段(使用点语法)。
因为在任何servlet或websockets方法(get,put,onMessage)之前触发了contextInitialized,所以map将在那里。同时也是并发映射,它内部应该没有重复的id。
当然,您还需要清理会话地图的策略。总而言之,您必须与来自javax.servlet API的事件一起构建您的系统。
类似的例子:
package example;
import java.io.FileNotFoundException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.*;
/**
* Application lifecycle events. Handles:
* <ul>
* <li>start, shutdown of application
* <li>start, stop of session
* </ul>
*
* @author mitjag
*
*/
public class AppInit implements HttpSessionListener, ServletContextListener {
public static final Logger log = Logger.getLogger(AppInit.class.getCanonicalName());
public static final Map<String, HttpSession> SESSION_MAP = new ConcurrentHashMap<String, HttpSession>(); /* access AppInit.SESSION_MAP from anywhere in your app*/
@Override
public void contextInitialized(ServletContextEvent ctx) {}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// With this trick we maintain the list of sessionid's together with corresponding session
// It is used to grab the session if you have the valid session id
final String sid = arg0.getSession().getId();
log.info("SESSION CREATED with id " + arg0.getSession().getId());
SESSION_MAP.put(sid, arg0.getSession());
}
/**
* Called on session invalidation (manual or session timeout trigger, defined in web.xml (session-timeout)).
* @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent)
*/
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
// remove session from our list (see method: sessionCreated)
final String sid = arg0.getSession().getId();
SESSION_MAP.remove(sid);
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
}
}