IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE,sockjs-1.1.1,stomp-1.2搭建基于Tomcat-7.0.68的WebSocket应用

接着上文IntelliJ IDEA 2016.2使用Spring 4.3.1.RELEASE搭建基于Tomcat-7.0.68的WebSocket应用

上文的最后我们说到,WebSocket是需要定时心跳的,否则会在一段时间后自动断开连接,而更重要的是,不是所有的浏览器都支持WebSocket,早期的IE 10之前的版本就是不支持的,而这一部分的设备其实是不算少的,而sockjs的出现,恰恰好来解决了这个问题。对于不支持WebSocket的浏览器,sockjs使用了多种方式来兼容这种情况,包括使用长轮询等方式,Spring更是内建支持这种方式。

下面我们看如何在上篇文章的基础上,增加对于sockjs的支持。

首先是STOMP的文档官网地址 http://stomp.github.io/
代码的地址为https://github.com/jmesnil/stomp-websocket,项目下面的lib/stomp.js就是我们想要的文件。也可以本站下载stomp.js.zip

接下来sockjs的代码地址https://github.com/sockjs/sockjs-client,项目下面的dist/sockjs-1.1.1.js就是我们想要的文件。也可以本站下载sockjs-1.1.1.js.zip

接下来我们把下载到的文件放到我们工程目录下面的web->resources->javascript目录下面,如下图:

stomp-websockjs-resources

接下来,添加我们需要的com.fasterxml.jackson.core:jackson-annotations:2.8.1,com.fasterxml.jackson.core:jackson-core:2.8.1,com.fasterxml.jackson.core:jackson-databind:2.8.1这三个jar包,增加的方式参照上一篇中对于javax.servlet:javax.servlet-api:3.1.0的操作方法。与上一篇的操作不同的是,这次添加的三个jar包,都要放到编译完成后的War包中。最后的结果如下图:
ToolsJacksonMaven

ToolsJacksonMavenWar

下面,我们开始进行代码的操作,我们在上篇文章中的src->Tools->WebSocket中新增两个源代码文件SockJsController.java,WebJsSocketConfig.java.如下图:

NewJavaSourcesForSockjs

其中的代码如下:
SockJsController.java

package Tools.WebSocket;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class SockJsController {

        @MessageMapping("/hello")
        @SendTo("/hello/subscribe") /*貌似这个名字可以随意的,主要用在stomp.subscribe时候的名字*/
        public String Hello(String message) throws Exception {
            return new String("Hello");
        }
}

WebJsSocketConfig.java

package Tools.WebSocket;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;


@Configuration
@EnableWebSocketMessageBroker
public class WebJsSocketConfig  extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/webSocketServer");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").setAllowedOrigins("*").withSockJS();
    }
}

然后修改WebSocket.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>WebSocket/SockJS Echo Sample (Adapted from Tomcat's echo sample)</title>
    <style type="text/css">
        #connect-container {
            float: left;
            width: 400px
        }

        #connect-container div {
            padding: 5px;
        }

        #console-container {
            float: left;
            margin-left: 15px;
            width: 400px;
        }

        #console {
            border: 1px solid #CCCCCC;
            border-right-color: #999999;
            border-bottom-color: #999999;
            height: 170px;
            overflow-y: scroll;
            padding: 5px;
            width: 100%;
        }

        #console p {
            padding: 0;
            margin: 0;
        }
    </style>

    <script src="./resources/javascript/sockjs-1.1.1.js"></script>
    <script src="./resources/javascript/stomp.js"></script>

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

        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, {transports: transports}) : new WebSocket(url);
            if((url.indexOf('sockjs') != -1)) {
                stompClient = Stomp.over(ws);
                stompClient.connect({}, function(frame) {
                    setConnected(true);
                    log('Connected: ' + frame);
                    stompClient.subscribe('/hello/subscribe', function(message){
                        log(message.body);
                    });
                });
            }else {
                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;
            }
            stompClient = null;
            setConnected(false);
        }

        function echo() {
            if(stompClient != null){
                var message = document.getElementById('message').value;
                stompClient.send("/webSocketServer/hello", {}, message);
                log('Sent: ' + message);
            }else {
                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('/webSocketServer');">
        <label for="radio1">W3C WebSocket</label>
        <br>
        <input id="radio2" type="radio" name="group1" onclick="updateUrl('/webSocketServer/sockjs/hello');">
        <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>

</body>
</html>

最后,我们修改web->WEB-INF->web.xml,在其中增加

<servlet-mapping>
	<servlet-name>dispatcher</servlet-name>
	<url-pattern>/webSocketServer/sockjs/*</url-pattern>
</servlet-mapping>

修改后的最终结果如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>Tools.Filter.StrutsPrepareAndExecuteFilterEx</filter-class>
        <async-supported>true</async-supported>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.form</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/webSocketServer/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/webSocketServer/sockjs/*</url-pattern>
    </servlet-mapping>
</web-app>

参考链接


 

发布者

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注