SpringBoot學習-(十二)SpringBoot中建立WebSocket連線
阿新 • • 發佈:2018-12-31
WebSocket握手圖解:
建立連線的步驟:
- pom檔案中新增依賴
- 建立握手攔截器
- 建立WebSocket處理類
- 配置WebSocket
- 前端頁面訪問
專案目錄結構:
1.pom檔案中新增依賴
<!-- springboot websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency >
2.建立握手攔截器
用於進行握手之前和握手之後的操作
一般用於握手之前將使用者資訊交給WebSocketSession管理
之後可以在WebSocket處理類中獲取使用者資訊
package com.ahut.websocket;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
/**
*
* @ClassName: MyWebSocketInterceptor
* @Description: 建立握手 此類用來獲取登入使用者資訊並交由websocket管理
* @author cheng
* @date 2017年9月26日 上午10:31:30
*/
/**
* HandshakeInterceptor WebSocket握手請求的攔截器. 檢查握手請求和響應, 對WebSocketHandler傳遞屬性
*/
public class MyWebSocketInterceptor implements HandshakeInterceptor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 在握手之前執行該方法, 繼續握手返回true, 中斷握手返回false. 通過attributes引數設定WebSocketSession的屬性
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
logger.info("xxx使用者建立連線。。。");
if (request instanceof ServletServerHttpRequest) {
String userId = ((ServletServerHttpRequest) request).getServletRequest().getParameter("userId");
attributes.put("userId", userId);
logger.info("使用者唯一標識:" + userId);
}
return true;
}
/**
* 在握手之後執行該方法. 無論是否握手成功都指明瞭響應狀態碼和相應頭.
*/
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
}
}
3.建立WebSocket處理類
處理類的層級關係:
package com.ahut.websocket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
/**
*
* @ClassName: WebSocketPushHandler
* @Description: 建立處理器
* @author cheng
* @date 2017年9月26日 上午10:36:17
*/
public class WebSocketPushHandler extends TextWebSocketHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private static final List<WebSocketSession> userList = new ArrayList<>();
/**
* 使用者進入系統監聽
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
logger.info("xxx使用者進入系統。。。");
logger.info("使用者資訊:" + session.getAttributes());
Map<String, Object> map = session.getAttributes();
for (String key : map.keySet()) {
logger.info("key:" + key + " and value:" + map.get(key));
}
userList.add(session);
}
/**
* 處理使用者請求
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
logger.info("系統處理xxx使用者的請求資訊。。。");
}
/**
* 使用者退出後的處理
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
if (session.isOpen()) {
session.close();
}
userList.remove(session);
logger.info("xxx使用者退出系統。。。");
}
/**
* 自定義函式
* 給所有的線上使用者傳送訊息
*/
public void sendMessagesToUsers(TextMessage message) {
for (WebSocketSession user : userList) {
try {
// isOpen()線上就傳送
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getLocalizedMessage());
}
}
}
/**
* 自定義函式
* 傳送訊息給指定的線上使用者
*/
public void sendMessageToUser(String userId, TextMessage message) {
for (WebSocketSession user : userList) {
if (user.getAttributes().get("userId").equals(userId)) {
try {
// isOpen()線上就傳送
if (user.isOpen()) {
user.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getLocalizedMessage());
}
}
}
}
}
4.配置WebSocket
package com.ahut.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.HandshakeInterceptor;
import com.ahut.websocket.MyWebSocketInterceptor;
import com.ahut.websocket.WebSocketPushHandler;
/**
*
* @ClassName: WebSocketConfig
* @Description: websocket配置類
* @author cheng
* @date 2017年9月26日 上午10:45:45
*/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
/**
* 註冊WebSocket處理類
*/
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(createWebSocketPushHandler(), "/webSocketServer")
.addInterceptors(createHhandshakeInterceptor()).setAllowedOrigins("*");
registry.addHandler(createWebSocketPushHandler(), "/sockjs/webSocketServer")
.addInterceptors(createHhandshakeInterceptor()).withSockJS();
}
/**
*
* @Title: createHhandshakeInterceptor
* @Description: 握手攔截器
* @return
*/
@Bean
public HandshakeInterceptor createHhandshakeInterceptor() {
return new MyWebSocketInterceptor();
}
/**
*
* @Title: createWebSocketPushHandler
* @Description: 處理類
* @return
*/
@Bean
public WebSocketHandler createWebSocketPushHandler() {
return new WebSocketPushHandler();
}
}
5.前端頁面訪問
<!DOCTYPE html>
<html>
<head>
<title>Java後端WebSocket的Tomcat實現</title>
</head>
<body>
Welcome<br/><input id="text" type="text"/>
<button onclick="send()">傳送訊息</button>
<hr/>
<button onclick="closeWebSocket()">關閉WebSocket連線</button>
<hr/>
<div id="message"></div>
</body>
<script type="text/javascript">
var websocket = null;
//判斷當前瀏覽器是否支援WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/webSocketServer?userId=wrwefesdfwetrwe324324");
}
else {
alert('當前瀏覽器 Not support websocket')
}
//連線發生錯誤的回撥方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket連線發生錯誤");
};
//連線成功建立的回撥方法
websocket.onopen = function () {
setMessageInnerHTML("WebSocket連線成功");
}
//接收到訊息的回撥方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
}
//連線關閉的回撥方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket連線關閉");
}
//監聽視窗關閉事件,當視窗關閉時,主動去關閉websocket連線,防止連線還沒斷開就關閉視窗,server端會拋異常。
window.onbeforeunload = function () {
closeWebSocket();
}
//將訊息顯示在網頁上
function setMessageInnerHTML(innerHTML) {
document.getElementById('message').innerHTML += innerHTML + '<br/>';
}
//關閉WebSocket連線
function closeWebSocket() {
websocket.close();
}
//傳送訊息
function send() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</html>
開啟頁面後臺日誌列印結果: