tomcat 7.0.68ベースのwebsocket実装、およびHttpSessionIdによるwebsocketセッション共有


0、ページ呼び出しコードを貼っておきます
var historyWebsocket = null;
//  var websocketOnline = null;

      //           WebSocket
    if('WebSocket' in window){
        historyWebsocket = new WebSocket("ws://ip:  /   /historyWebsocket");
    }
    else{
        alert('Not support websocket')
    }

  //           
    historyWebsocket.onerror = function(){
        setMessageInnerHTML("error");
    };

    //           
    historyWebsocket.onopen = function(event){
        send();
    }
 //          
    historyWebsocket.onmessage = function(event){

        var data = eval("("+event.data+")");//     
    }

    //         
    historyWebsocket.onclose = function(){
        setMessageInnerHTML("close");
    }


    //        ,      ,     websocket  ,             ,server     。
    window.onbeforeunload = function(){
        historyWebsocket.close();
    }

    //         
    function setMessageInnerHTML(innerHTML){
        $("#message").empty();
        document.getElementById('message').innerHTML +='' +innerHTML + '
'
; } // function closeWebSocket(){ historyWebsocket.close(); } // function send(){ // var message = document.getElementById('text').value; // mesg="14701661345"; // historyWebsocket.send(message); }

1、onlineWebsocket.java
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;





//         URI,         URI    WebSocket。  Servlet   mapping。   web.xml   。
@ServerEndpoint(value="/onlineWebsocket",configurator=GetHttpSessionConfigurator.class)
public class OnlineStateWebSocket {
    private static final Logger LOG = LoggerFactory.getLogger(OnlineStateWebSocket.class);

    //    ,           。            。
    private static int onlineCount = 0;

    //concurrent      Set,            MyWebSocket  。                 ,    Map   ,  Key       
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();

    //     sim          session  map  ,key  sim   ,value       session   
    private static ConcurrentHashMap> simSessionWebSocketMap = new ConcurrentHashMap>();

    //     httpSessionId/session  map  ,key  httpSessionId ,value       session   
    private static ConcurrentHashMap httpSessionWebSocketMap = new ConcurrentHashMap();


    //           ,              
    private Session session;

    private HttpSession httpSession;

    /**
     *            
     * @param session       。session            ,              
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        this.session = session;
        webSocketSet.add(this);     //  set 
        addOnlineCount();           //    1

        this.httpSession = (HttpSession) config.getUserProperties()
                .get(HttpSession.class.getName());
        //     httpSession
        httpSessionWebSocketMap.put(this.httpSession.getId(), this);


        System.out.println("    :      !       " + getOnlineCount());
    }

    /**
     *          
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  // set   
        subOnlineCount();           //    1    

        Set>> entrySet = simSessionWebSocketMap.entrySet();

        Iterator>> iterator = entrySet.iterator();
        while(iterator.hasNext()){

            Entry> next = iterator.next();

            String key = next.getKey();    //  sim  

            ArrayList value = next.getValue(); //  sim         websocket  

            if(value.contains(this)){
                if(value.size()>1){
                    value.remove(this);
                    simSessionWebSocketMap.replace(key, value);
                }else{
                    simSessionWebSocketMap.remove(key);
                }

            }
        }

        System.out.println("    :      !       " + getOnlineCount());
    }

    /**
     *              
     * @param message           
     * @param session      
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("    :        :" + message);

        String[] SimArray = message.split(",");

        this.session = session;
        webSocketSet.add(this);     //  set 

        for(String sim:SimArray){

             ArrayList vehicleClientList ;

             if(simSessionWebSocketMap.get(sim.trim()) != null){
                vehicleClientList=simSessionWebSocketMap.get(sim.trim());   //    sim         session

                vehicleClientList.add(this);
                simSessionWebSocketMap.replace(sim.trim(), vehicleClientList);
             }else{
                vehicleClientList= new ArrayList();
                vehicleClientList.add(this);

                 simSessionWebSocketMap.put(sim.trim(), vehicleClientList);
             }

        }

    }

    /**
     *        
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("    :    ");
        error.printStackTrace();
    }

    /**
     *               。     ,            。
     * @param message
     * @throws IOException
     */
    public   void sendMessage(String message,HttpServletRequest request) throws IOException{
        if(this.session.isOpen()){
            this.session.getBasicRemote().sendText(message);
            this.session.setMaxTextMessageBufferSize(102400);
//          this.session.getAsyncRemote().sendText(message);
        }

    }

    public   void sendMessage(String message) throws IOException{

        if(this.session.isOpen()){
            this.session.getBasicRemote().sendText(message);
            this.session.setMaxTextMessageBufferSize(102400);
//          this.session.getAsyncRemote().sendText(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        OnlineStateWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        OnlineStateWebSocket.onlineCount--;
    }

    public static CopyOnWriteArraySet getWebSocketSet() {
        return webSocketSet;
    }

    public static void setWebSocketSet(CopyOnWriteArraySet webSocketSet) {
        OnlineStateWebSocket.webSocketSet = webSocketSet;
    }



}

2、RealWebsocket.java

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;





//         URI,         URI    WebSocket。  Servlet   mapping。   web.xml   。
@ServerEndpoint(value ="/realWebsocket",configurator=GetHttpSessionConfigurator.class)
public class RealWebSocket {
    private static final Logger LOG = LoggerFactory.getLogger(RealLocationWebSocket.class);


    //    ,           。            。
    private static int onlineCount = 0;

    //concurrent      Set,            MyWebSocket  。                 ,    Map   ,  Key       
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();

    //     sim          session  map  ,key  sim   ,value       session   
    private static ConcurrentHashMap> simSessionWebSocketMap = new ConcurrentHashMap>();

    //     httpSessionId/session  map  ,key  httpSessionId ,value       session   
    private static ConcurrentHashMap httpSessionWebSocketMap = new ConcurrentHashMap();


    //           ,              
    private Session session;

    private HttpSession httpSession;

    /**
     *            
     * @param session       。session            ,              
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config){
        this.session = session;
        webSocketSet.add(this);     //  set 
        addOnlineCount();           //    1


        this.httpSession = (HttpSession) config.getUserProperties()
                .get(HttpSession.class.getName());
        //     httpSession
        httpSessionWebSocketMap.put(this.httpSession.getId(), this);

        System.out.println("    :      !       " + getOnlineCount());
    }

    /**
     *          
     */
    @OnClose
    public void onClose(){
        webSocketSet.remove(this);  // set   
        subOnlineCount();           //    1    

        Set>> entrySet = simSessionWebSocketMap.entrySet();

        Iterator>> iterator = entrySet.iterator();
        while(iterator.hasNext()){

            Entry> next = iterator.next();

            String key = next.getKey();    //  sim  

            ArrayList value = next.getValue(); //  sim         websocket  

            if(value.contains(this)){
                if(value.size()>1){
                    value.remove(this);
                    simSessionWebSocketMap.replace(key, value);
                }else{
                    simSessionWebSocketMap.remove(key);
                }

            }
        }


        System.out.println("    :      !       " + getOnlineCount());
    }

    /**
     *              
     * @param message           
     * @param session      
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("    :        :" + message);


        String[] SimArray = message.split(",");

        this.session = session;
        webSocketSet.add(this);     //  set 

        for(String sim:SimArray){

             ArrayList vehicleClientList ;

             if(simSessionWebSocketMap.get(sim.trim()) != null){
                vehicleClientList=simSessionWebSocketMap.get(sim.trim());   //    sim         session
                vehicleClientList.add(this);
                simSessionWebSocketMap.replace(sim.trim(), vehicleClientList);
             }else{
                vehicleClientList= new ArrayList();
                vehicleClientList.add(this);

                 simSessionWebSocketMap.put(sim.trim(), vehicleClientList);
             }

        }

    }

    /**
     *        
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){
        System.out.println("    :    ");
        error.printStackTrace();
    }

    /**
     *               。     ,            。
     * @param message
     * @throws IOException
     */
    public   void sendMessage(String message,HttpServletRequest request) throws IOException{
        if(this.session.isOpen()){
            this.session.getBasicRemote().sendText(message);
            this.session.setMaxTextMessageBufferSize(102400);
//          this.session.getAsyncRemote().sendText(message);

        }

    }

    public   void sendMessage(String message) throws IOException{

        if(this.session.isOpen()){
            this.session.getBasicRemote().sendText(message);
            this.session.setMaxTextMessageBufferSize(102400);
//          this.session.getAsyncRemote().sendText(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        RealLocationWebSocket.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        RealLocationWebSocket.onlineCount--;
    }

    public static CopyOnWriteArraySet getWebSocketSet() {
        return webSocketSet;
    }

    public static void setWebSocketSet(CopyOnWriteArraySet webSocketSet) {
        RealLocationWebSocket.webSocketSet = webSocketSet;
    }


}

3、最後はhttpSessionIdによるwebsocket session共有
まずRealWebSocket.javaとOnlineWebsocketに登場したGetHttpSessionConfigurator.classを実現する
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.websocket.Extension;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator
{

    @Override
    public  T getEndpointInstance(Class clazz)
            throws InstantiationException {
        try {
            return clazz.newInstance();
        } catch (IllegalAccessException e) {
            InstantiationException ie = new InstantiationException();
            ie.initCause(e);
            throw ie;
        }
    }


    @Override
    public String getNegotiatedSubprotocol(List supported,
            List requested) {

        for (String request : requested) {
            if (supported.contains(request)) {
                return request;
            }
        }
        return "";
    }


    @Override
    public List getNegotiatedExtensions(List installed,
            List requested) {

        List result = new ArrayList<>();
        for (Extension request : requested) {
            if (installed.contains(request)) {
                result.add(request);
            }
        }
        return result;
    }


    @Override
    public boolean checkOrigin(String originHeaderValue) {
        return true;
    }

    @Override
    public void modifyHandshake(ServerEndpointConfig config, 
                                HandshakeRequest request, 
                                HandshakeResponse response)
    {
        HttpSession httpSession = (HttpSession)request.getHttpSession();
        config.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

上のフィルターの中で、もし意外でなければ、あなたは空のポインタを報告します.だから、ここで修復します.
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        // TODO Auto-generated method stub

    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpSession session = ((HttpServletRequest) sre.getServletRequest()).getSession();
    }

}

また、このフィルタをweb.xmlに追加します.
    
        com.vshop.sys.listener.RequestListener
    

これで終わったら、何の問題もないはずです.
OnlineWebsocket.javaとRealWebsocket.javaのhttpSessionWebSocketMap変数で2つのwebssocket Session共有を実現します.