Spring4+WebSocket搭建

首先,支持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消息中心结合实现了客户端提醒异步推送,后期更新文章!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值