場景
websocket是Html5新增加特性之一,目的是瀏覽器與服務端建立全雙工的通信方式,解決http請求-響應帶來過多的資源消耗,同時對特殊場景應用提供了全新的實現方式,比如聊天、股票交易、游戲等對對實時性要求較高的行業領域。
背景
在瀏覽器中通過http僅能實現單向的通信,comet可以一定程度上模擬雙向通信,但效率較低,并需要服務器有較好的支持; flash中的socket和xmlsocket可以實現真正的雙向通信,通過 flex ajax bridge,可以在javascript中使用這兩項功能. 可以預見,如果websocket一旦在瀏覽器中得到實現,將會替代上面兩項技術,得到廣泛的使用.面對這種狀況,HTML5定義了WebSocket協議,能更好的節省服務器資源和帶寬并達到實時通訊。目前各大主流瀏覽器都支持websocket,IE瀏覽器要IE10+
一、POM依賴
POM依賴,spring4.1.4.RELEASE,spring核心依賴請自行添加,下面是websocket相關jar
1
2
3
4
5
6
7
8
9
10
11
|
< dependency > < groupId >javax.websocket</ groupId > < artifactId >javax.websocket-api</ artifactId > < version >1.0</ version > < scope >provided</ scope > </ dependency > < dependency > < groupId >org.springframework</ groupId > < artifactId >spring-websocket</ artifactId > < version >4.1.4.RELEASE</ version > </ dependency > |
二、WebSocket入口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@Configuration @EnableWebMvc @EnableWebSocket public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { //允許連接的域,只能以http或https開頭 String[] allowsOrigins = { "http://www.xxx.com" }; //WebIM WebSocket通道 registry.addHandler(chatWebSocketHandler(), "/ webSocketIMServer" ).setAllowedOrigins(allowsOrigins).addInterceptors(myInterceptor()); registry.addHandler(chatWebSocketHandler(), "/sockjs/w ebSocketIMServer" ).setAllowedOrigins(allowsOrigins).addInterceptors(myInterceptor()).withSockJS(); } @Bean public ChatWebSocketHandler chatWebSocketHandler() { return new ChatWebSocketHandler(); } @Bean public WebSocketHandshakeInterceptor myInterceptor(){ return new WebSocketHandshakeInterceptor(); } } |
1.實現WebSocketConfigurer接口,重寫registerWebSocketHandlers方法,這是一個核心實現方法,配置websocket入口,允許訪問的域、注冊Handler、SockJs支持和攔截器。
2.registry.addHandler注冊和路由的功能,當客戶端發起websocket連接,把/path交給對應的handler處理,而不實現具體的業務邏輯,可以理解為收集和任務分發中心。
3.setAllowedOrigins(String[] domains),允許指定的域名或IP(含端口號)建立長連接,如果只允許自家域名訪問,這里輕松設置。如果不限時使用"*"號,如果指定了域名,則必須要以http或https開頭。
4.addInterceptors,顧名思義就是為handler添加攔截器,可以在調用handler前后加入我們自己的邏輯代碼。
5.spring websocket也支持STOMP協議,下回再分享。
三、攔截器實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class WebSocketHandshakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object > attributes) throws Exception { if (request instanceof ServletServerHttpRequest) { attributes.put( "username" ,userName); } return true ; } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } } |
beforeHandshake,在調用handler前處理方法。常用在注冊用戶信息,綁定WebSocketSession,在handler里根據用戶信息獲取WebSocketSession發送消息。
四、Handler處理類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
public class ChatWebSocketHandler extends TextWebSocketHandler{ private final static List<WebSocketSession> sessions = Collections.synchronizedList( new ArrayList<WebSocketSession>()); //接收文本消息,并發送出去 @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { chatTextMessageHandler(message.getPayload()); super .handleTextMessage(session, message); } //連接建立后處理 @SuppressWarnings ( "unchecked" ) @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { logger.debug( "connect to the websocket chat success......" ); sessions.add(session); //處理離線消息 } //拋出異常時處理 @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { if (session.isOpen()){ session.close(); } logger.debug( "websocket chat connection closed......" ); sessions.remove(session); } //連接關閉后處理 @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { logger.debug( "websocket chat connection closed......" ); sessions.remove(session); } @Override public boolean supportsPartialMessages() { return false ; } } |
五、客戶端連接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
var host = window.location.host; var websocket; if ( 'WebSocket' in window) { websocket = new ReconnectingWebSocket( "ws://" + host + "/webSocketIMServer" , null , {debug: true , maxReconnectAttempts: 4 }); } else if ( 'MozWebSocket' in window) { websocket = new MozWebSocket( "ws://" + host + "/webSocketIMServer" ); } else { websocket = new SockJS( "http://" + host + "/sockjs/webSocketIMServer" ); } websocket.onopen = function(evnt) { console.log( "websocket連接上" ); }; websocket.onmessage = function(evnt) { messageHandler(evnt.data); }; websocket.onerror = function(evnt) { console.log( "websocket錯誤" ); }; websocket.onclose = function(evnt) { console.log( "websocket關閉" ); } |
這里用到了ReconnectingWebSocket.js,對瀏覽器自帶websocket添加了擴展,例如重連,連接超時時間,失敗重連間隔,嘗試連接最大次數等。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/nosqlcoco/p/5860730.html