WebSocket 是 HTML5 一種新的協議。它實現了瀏覽器與服務器全雙工通訊,能更好的節省服務器資源和帶寬並達到實時通信,它創建在 TCP 之上,同 HTTP 同樣經過 TCP 來傳輸數據,可是它和 HTTP 最大不一樣是:javascript
本示例爲演示WebSocket的廣播式模式,即服務端有消息時,會將消息發送給全部鏈接了當前endpoint的 Browser/Client Agenthtml
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.version>4.3.8.RELEASE</spring.version> </properties> <dependencies> <!-- springmvc jar --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- WEBSOCKET的JAR --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>${spring.version}</version> </dependency> </dependencies>
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 //開啓對WebSocket的支持 @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{ /** * 註冊一個STOMP協議的節點,並映射到指定的URL * @param registry */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { //註冊一個STOMP的endpoint,並指定使用SockJS協議 registry.addEndpoint("/endpointSocket").withSockJS(); } /** * 配置消息代理 * @param registry */ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { //配置一個廣播式的消息代理 registry.enableSimpleBroker("/topic"); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:websocket="http://www.springframework.org/schema/websocket" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan> <mvc:annotation-driven/> <mvc:resources mapping="/js/**" location="/js/"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/"/> <property name="suffix" value=".jsp"/> </bean> <!-- /app:客戶端向服務端 發送的前綴 --> <websocket:message-broker application-destination-prefix="/app"> <websocket:stomp-endpoint path="/ws"> <websocket:sockjs/> </websocket:stomp-endpoint> <!-- 服務端向客戶端 發送的前綴 --> <websocket:simple-broker prefix="/topic"/> </websocket:message-broker> </beans>
import java.util.Map; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; /** * 由客戶端觸發,並接受服務器發送信息的例子 */ @Controller public class MessageController { @RequestMapping(value = "/websocket", method = { RequestMethod.GET }) public String toHello() { System.out.println("messageController ----> tohello()"); return "websocket"; //定位到頁面 } @MessageMapping("/greeting") @SendTo("/topic/greetings") public String greeting(Map<String, Object> message) throws Exception { System.out.println("MessageController====================================>客戶端鏈接"); return "服務器返回: Hello,客戶端輸入信息< " + message.get("name") + ">"; } }
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ page session="false"%> <% String path = request.getContextPath(); // path = "/travel" String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Spring + WebSocket Hello world例子</title> <script src="<%=basePath%>js/sockjs-1.1.1.min.js"></script> <script src="<%=basePath%>js/stomp-2.3.4.min.js"></script> <script src="<%=basePath%>/js/jquery-1.10.2.js"></script> <script src="<%=basePath%>/js/jquery-ui-1.10.4.custom.js"></script> <script src="<%=basePath%>/js/jquery.json.js"></script> <script> //建立sockJS協議 var socket = new SockJS("<c:url value='/ws'/>"); var stompClient = Stomp.over(socket); //鏈接服務器 //stompClient.connect("guest", "guest", function() {}); 用戶名和密碼 stompClient.connect({}, function(frame) { //setConnected(true); $("#recFromServer").append("<br>" + "成功鏈接服務器.!"); console.log('Connected: ' + frame); window.alert('Connected: ' + frame); //subscribe:訂閱一個主題,「/topic」前綴是在: stompClient.subscribe('/topic/greetings', function(greeting) { console.log(greeting.body); console.log("本身的操做!"); var content = JSON.parse(greeting.body).content; $("#recFromServer").append("<br>" + content); }); }); function sendMessage() { //發送信息給服務器 stompClient.send("/app/greeting", {}, JSON.stringify({ 'name' : $("#message").val() })); } </script> </head> <body> 輸入名稱:${basePath } <input id="message" type="text"> <input type="button" onclick="sendMessage()" value="發送到服務器"> <div id="recFromServer"></div> 測試方式: 用兩個瀏覽器打開這個頁面,而後一個頁面提交信息,它能接收到服務器的數據,同時另外一個頁面也能接收到服務器發送的數據。 </body> </html>
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>My WebSocket</title> </head> <body> <input id="text" type="text" /> <button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> <div id="message"> </div> </body> <script type="text/javascript"> var websocket = null; //判斷當前瀏覽器是否支持WebSocket if('WebSocket' in window){ //若是支持WebSocket,發起WebSocket鏈接 websocket = new WebSocket("ws://localhost:8088/websocket"); } else{ alert('Not support websocket') } //鏈接發生錯誤的回調方法 websocket.onerror = function(){ setMessageInnerHTML("error"); }; //鏈接成功創建的回調方法 websocket.onopen = function(event){ setMessageInnerHTML("open"); } //接收到消息的回調方法 websocket.onmessage = function(event){ setMessageInnerHTML(event.data); } //鏈接關閉的回調方法 websocket.onclose = function(){ setMessageInnerHTML("close"); } //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket鏈接,防止鏈接還沒斷開就關閉窗口,server端會拋異常。 window.onbeforeunload = function(){ //關閉鏈接 websocket.close(); } //將消息顯示在網頁上 function setMessageInnerHTML(innerHTML){ document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //關閉鏈接 function closeWebSocket(){ websocket.close(); } //發送消息 function send(){ var message = document.getElementById('text').value; //發送消息 websocket.send(message); } </script> </html>
也可打開多個瀏覽器窗口鏈接到WebSocket服務端,在其中一個瀏覽器窗口中點擊獲取服務器時間,其餘兩個也將接收到消息html5