Jetty中的轻量级IPC到WebSocketListener

时间:2016-05-23 07:44:44

标签: websocket jetty ipc jetty-9 java-websocket

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);

1 个答案:

答案 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) {

    }

}