Spring4+WebSocket搭建

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhenghuasheng/article/details/51719959

首先,支持spring websocket的tomcat、jetty版本,官方文档有申明:

25.2 WebSocket API The Spring Framework provides a WebSocket API designed to adapt to various WebSocket engines. Currently the list
includes WebSocket runtimes such as Tomcat 7.0.47+, Jetty 9.1+,
GlassFish 4.1+, WebLogic 12.1.3+, and Undertow 1.0+ (and WildFly
8.0+). Additional support may be added as more WebSocket runtimes become available.

[Note] As explained in the introduction, direct use of a WebSocket API
is too low level for applications — until assumptions are made about
the format of a message there is little a framework can do to
interpret messages or route them via annotations. This is why
applications should consider using a sub-protocol and Spring’s STOMP
over WebSocket support. When using a higher level protocol, the
details of the WebSocket API become less relevant, much like the
details of TCP communication are not exposed to applications when
using HTTP. Nevertheless this section covers the details of using
WebSocket directly.

本人因使用内置jetty版本为jetty6,可以初始化成功,但会出现无法找到websocket容器问题,最终选择使用tomcat8来完成。

第一步:编写handler,需继承TextWebSocketHandler,并覆盖父类方法afterConnectionEstablished、handleMessage、afterConnectionClosed.

源码:

/**
 * Created by zhenghuasheng on 2016/6/19.
 */
public class WebSocketHandler extends TextWebSocketHandler {
    private List<WebSocketSession> socketSessions = new ArrayList<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        socketSessions.add(session);
        super.afterConnectionEstablished(session);
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        sendMessageToUser((TextMessage) message);

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        socketSessions.remove(session);
        super.afterConnectionClosed(session, status);
    }

    public void sendMessageToUser(TextMessage message) throws IOException {
        for (WebSocketSession   socketSession : socketSessions){
            if (socketSession.isOpen()) {
                socketSession.sendMessage(message);
            }
        }
    }
}

afterConnectionEstablished:连接完成时被调用,
afterConnectionClosed:连接关闭时被调用,
handleMessage:发送消息时被调用。

第二步,编写socket握手拦截器
1,如果不需要从请求中获取attributes,等属性值,而使用广播的形式对所有登录的客户端都推送消息,直接使用org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor即可,

2,如果需要对指定的用户或其他根据客户端特性来操作将需要自己重写拦截器:比如源码中从获取了userId参数
有两种方式
* 一种是实现接口HandshakeInterceptor,实现beforeHandshake和afterHandshake函数
* 一种是继承HttpSessionHandshakeInterceptor,重载beforeHandshake和afterHandshake函数
*我这里是参照spring官方文档中的继承HttpSessionHandshakeInterceptor的方式
源代码:

 /**
 * Created by zhenghuasheng on 2016/6/20.
 */
public class WebSocketSessionHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
    Logger logger = LoggerFactory.getLogger(WebSocketSessionHandshakeInterceptor.class);

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
        if (getSession(request) != null) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpServletRequest httpServletRequest = servletRequest.getServletRequest();
            attributes.put("userId", httpServletRequest.getParameter("userId"));
        }
        super.beforeHandshake(request, response, wsHandler, attributes);
        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
        super.afterHandshake(request, response, wsHandler, ex);
    }
    private HttpSession getSession(ServerHttpRequest request) {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
            return serverRequest.getServletRequest().getSession();
        }
        return null;
    }

第三步,配置文件编写

<websocket:handlers allowed-origins="*">
        <websocket:mapping path="/webSocketHandler" handler="webSocketHandler"/>
        <websocket:handshake-interceptors>
            <bean class="com.order.web.interceptor.WebSocketSessionHandshakeInterceptor"/>
        </websocket:handshake-interceptors>
        <!--<websocket:sockjs/>-->
    </websocket:handlers>

    <websocket:handlers allowed-origins="*">
        <websocket:mapping path="/sockjs/webSocketHandler" handler="webSocketHandler"/>
        <websocket:sockjs/>
    </websocket:handlers>
    <bean class="org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean">
        <property name="maxTextMessageBufferSize" value="8192"/>
        <property name="maxBinaryMessageBufferSize" value="8192"/>
    </bean>

web.xml中配置请求处理路径

<servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/api/*</url-pattern>
</servlet-mapping>   

第四步,页面js,demo

<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>

    <script type="text/javascript">
        var ws = null;
        var url = null;
        var transports = [];

        function setConnected(connected) {
            document.getElementById('connect').disabled = connected;
            document.getElementById('disconnect').disabled = !connected;
            document.getElementById('echo').disabled = !connected;
        }

        function connect() {
            if (!url) {
                alert('Select whether to use W3C WebSocket or SockJS');
                return;
            }
            ws = (url.indexOf('sockjs') != -1) ? new SockJS(url, undefined, {protocols_whitelist: transports}) : new WebSocket(url);

            ws.onopen = function () {
                setConnected(true);
                log('Info: connection opened.');
            };
            ws.onmessage = function (event) {
                log('Received: ' + event.data);
            };
            ws.onclose = function (event) {
                setConnected(false);
                log('Info: connection closed.');
                log(event);
            };
        }

        function disconnect() {
            if (ws != null) {
                ws.close();
                ws = null;
            }
            setConnected(false);
        }

        function echo() {
            if (ws != null) {
                var message = document.getElementById('message').value;
                log('Sent: ' + message);

                ws.send(message);
            } else {
                alert('connection not established, please connect.');
            }
        }

        function updateUrl(urlPath) {
            if (urlPath.indexOf('sockjs') != -1) {
                url = urlPath;
                document.getElementById('sockJsTransportSelect').style.visibility = 'visible';
            }
            else {
              if (window.location.protocol == 'http:') {
                  url = 'ws://' + window.location.host + urlPath;
              } else {
                  url = 'wss://' + window.location.host + urlPath;
              }
              document.getElementById('sockJsTransportSelect').style.visibility = 'hidden';
            }
        }

        function updateTransport(transport) {
          transports = (transport == 'all') ?  [] : [transport];
        }

        function log(message) {
            var console = document.getElementById('console');
            var p = document.createElement('p');
            p.style.wordWrap = 'break-word';
            p.appendChild(document.createTextNode(message));
            console.appendChild(p);
            while (console.childNodes.length > 25) {
                console.removeChild(console.firstChild);
            }
            console.scrollTop = console.scrollHeight;
        }
    </script>
</head>
<body>
<noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websockets 
    rely on Javascript being enabled. Please enable
    Javascript and reload this page!</h2></noscript>
<div>
    <div id="connect-container">
        <input id="radio1" type="radio" name="group1" onclick="updateUrl('/api/webSocketHandler?userId=18820003515');">
            <label for="radio1">W3C WebSocket</label>
        <br>
        <input id="radio2" type="radio" name="group1" onclick="updateUrl('/api/sockjs/webSocketHandler');">
            <label for="radio2">SockJS</label>
        <div id="sockJsTransportSelect" style="visibility:hidden;">
            <span>SockJS transport:</span>
            <select onchange="updateTransport(this.value)">
              <option value="all">all</option>
              <option value="websocket">websocket</option>
              <option value="xhr-polling">xhr-polling</option>
              <option value="jsonp-polling">jsonp-polling</option>
              <option value="xhr-streaming">xhr-streaming</option>
              <option value="iframe-eventsource">iframe-eventsource</option>
              <option value="iframe-htmlfile">iframe-htmlfile</option>
            </select>
        </div>
        <div>
            <button id="connect" onclick="connect();">Connect</button>
            <button id="disconnect" disabled="disabled" onclick="disconnect();">Disconnect</button>
        </div>
        <div>
            <textarea id="message" style="width: 350px">Here is a message!</textarea>
        </div>
        <div>
            <button id="echo" onclick="echo();" disabled="disabled">Echo message</button>
        </div>
    </div>
    <div id="console-container">
        <div id="console"></div>
    </div>
</div>

spring4+websocket,搭建完成,之前已将websocket和mq消息中心结合实现了客户端提醒异步推送,后期更新文章!

猜你喜欢

转载自blog.csdn.net/zhenghuasheng/article/details/51719959