WebSocket是爲解決客戶端與服務端實時通訊而產生的技術。其本質是先經過HTTP/HTTPS協議進行握手後建立一個用於交換數據的TCP鏈接,此後服務端與客戶端經過此TCP鏈接進行實時通訊。 javascript
之前咱們實現推送技術,用的都是輪詢,在特色的時間間隔有瀏覽器自動發出請求,將服務器的消息主動的拉回來,在這種狀況下,咱們須要不斷的向服務器 發送請求,然而HTTP request 的header是很是長的,裏面包含的數據可能只是一個很小的值,這樣會佔用不少的帶寬和服務器資源。會佔用大量的帶寬和服務器資源。 css
WebSocket 最偉大之處在於服務器和客戶端能夠在給定的時間範圍內的任意時刻,相互推送信息。在創建鏈接以後,服務器能夠主動傳送數據給客戶端。此外,服務器與客戶端之間交換的標頭信息很小。 html
WebSocket並不限於以Ajax(或XHR)方式通訊,由於Ajax技術須要客戶端發起請求,而WebSocket服務器和客戶端能夠彼此相互推送信息。 前端
如何使用?
注意:spring4.0之後加入了對websocket技術的支持,base項目的spring版本爲3.1.4,升到4.0.2後加入spring自帶的websocket包。 java
一、maven pom.xml加入websocket所依賴的jar包 jquery
<!-- websocket --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.3.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>4.0.1.RELEASE</version> </dependency>
二、在servlet-context中添加
http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd
handleTextMessage
消息處理方法,接收會話中前端發送給後臺的message,再經過sendMessage發送到前端
afterConnectionEstablished 鏈接創建後處理方法
afterConnectionClosed 鏈接關閉後處理方法
package cn.com.bmsoft.base.websocket; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.TextWebSocketHandler; import cn.com.bmsoft.base.service.face.management.IGasService; import cn.com.bmsoft.base.service.face.management.IHomeMonitorService; import cn.com.bmsoft.base.service.face.management.IInfraredService; @RequestMapping("websocket") public class WebsocketEndPoint extends TextWebSocketHandler { @Autowired IHomeMonitorService homeMonitorService; @Autowired IGasService gasService; @Autowired IInfraredService infraredService; @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { super.handleTextMessage(session, message); String phonemessage = message.getPayload(); session.sendMessage(message); } @Override public void afterConnectionEstablished(final WebSocketSession session) throws Exception { ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(1); System.out.println("Connection Establied!"); newScheduledThreadPool.scheduleWithFixedDelay(new TimerTask() { public void run() { try { Map<String, Object> queryParams = new HashMap<String, Object>(); queryParams.put("gStatus","1"); queryParams.put("iStatus","1"); //查詢未通知異常條數 int gwarns = gasService.count(queryParams); int iwarns = infraredService.count(queryParams); if((gwarns+iwarns)!=0){ session.sendMessage(new TextMessage((gwarns+iwarns)+"")); }else{ session.sendMessage(new TextMessage(0+"")); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, 0, 5000, TimeUnit.MILLISECONDS); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { System.out.println("Connection Closed!"); } }
四、建立握手協議 web
package cn.com.bmsoft.base.websocket; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor; import java.util.Map; public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { return super.beforeHandshake(request, response, wsHandler, attributes); } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) { super.afterHandshake(request, response, wsHandler, ex); } }五、servletcontext配置處理類和握手協議
<!-- spring-websocket配置start--> <bean id="websocket" class="cn.com.bmsoft.base.websocket.WebsocketEndPoint" /> <websocket:handlers> <websocket:mapping path="/websocket" handler="websocket" /> <websocket:handshake-interceptors> <bean class="cn.com.bmsoft.base.websocket.HandshakeInterceptor" /> </websocket:handshake-interceptors> </websocket:handlers> <!-- spring-websocket配置end-->
六、客戶端頁面 spring
<!DOCTYPE html> <html> <head> <title>websocket example</title> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=8,9,10" /> <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="http://cdn.sockjs.org/sockjs-0.3.min.js"></script> --> <script type="text/javascript" src="${requestContext.contextPath}/resources/scripts/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() { alert("url:"+url); if (!url) { alert('Select whether to use W3C WebSocket or SockJS'); return; } ws = new WebSocket(url); //申請一個WebSocket對象 ws.onopen = function () { setConnected(true); log('Info: connection opened.'); }; ws.onmessage = function (event) { //var msgJson=eval("("+event.data+")"); 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); var msg = '"frdId":"'+28+'",' + '"content":"' + message + '"'; ws.send(msg); // ws.send(message); } else { alert('connection not established, please connect.'); } } function updateUrl(urlPath) { if (window.location.protocol == 'http:') { url = 'ws://' + window.location.host + urlPath; } else { url = 'wss://' + window.location.host + urlPath; } } 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> <script type="text/javascript" src="${requestContext.contextPath}/resources/scripts/jquery-${jqueryVersion}.min.js"></script> <script type="text/javascript"> $(function(){ //移除頂端遮罩 if (top.hideMask) top.hideMask(); }); </script> <body> <div> <div id="connect-container"> <input id="radio1" type="radio" name="group1" onclick="updateUrl('/base/websocket');"> <label for="radio1">W3C WebSocket</label> <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>
sockjs-0.3.min.js連接:http://pan.baidu.com/s/1c2uLpDY 密碼:5zxh