接着上文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
目录下面,如下图:
接下来,添加我们需要的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
包中。最后的结果如下图:
下面,我们开始进行代码的操作,我们在上篇文章中的src
->Tools
->WebSocket
中新增两个源代码文件SockJsController.java
,WebJsSocketConfig.java
.如下图:
其中的代码如下:
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>
参考链接