中芯國際正式委任高永崗為董事長,周子學辭任董事
本節簡單介紹下如何在Spring Boot引入WebSocket,實現簡單的客戶端與服務端建立長連線並互發送文字訊息。
1.框架搭建
新建一個Spring Boot專案,artifactId為spring-boot-websocket-socketjs,專案結構如下圖所示:
專案的pom內容如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cc.mrbird</groupId> <artifactId>spring-boot-websocket-socketjs</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-websocket-socketjs</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
引入了spring-boot-starter-websocket和spring-boot-starter-web依賴。
2.構建服務端
在cc.mrbird.socket目錄下新建handler包,然後在該包下新建MyStringWebSocketHandler
繼承TextWebSocketHandler
:
@Component public class MyStringWebSocketHandler extends TextWebSocketHandler { private Logger log = LoggerFactory.getLogger(this.getClass()); @Override public void afterConnectionEstablished(WebSocketSession session) { log.info("和客戶端建立連線"); } @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { session.close(CloseStatus.SERVER_ERROR); log.error("連線異常", exception); } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { super.afterConnectionClosed(session, status); log.info("和客戶端斷開連線"); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { // 獲取到客戶端傳送過來的訊息 String receiveMessage = message.getPayload(); log.info(receiveMessage); // 傳送訊息給客戶端 session.sendMessage(new TextMessage(fakeAi(receiveMessage))); // 關閉連線 // session.close(CloseStatus.NORMAL); } private static String fakeAi(String input) { if (input == null || "".equals(input)) { return "你說什麼?沒聽清︎"; } return input.replace('你', '我') .replace("嗎", "") .replace('?', '!') .replace('?', '!'); } }
該類重寫了父類AbstractWebSocketHandler
的四個方法:
- afterConnectionEstablished,和客戶端連結成功的時候觸發該方法;
- handleTransportError,和客戶端連線失敗的時候觸發該方法;
- afterConnectionClosed,和客戶端斷開連線的時候觸發該方法;
- handleTextMessage,和客戶端建立連線後,處理客戶端傳送的請求。
WebSocketSession
物件代表每個客戶端會話,包含許多實用方法:
方法見名知意,就不贅述了。
此外,因為我們的目的是實現和客戶端的通訊,並且內容為文字內容,所以我們繼承的是TextWebSocketHandler
BinaryWebSocketHandler
,更多資訊可以自行檢視WebSocketHandler
的子類。
接著在cc.mrbird.socket目錄下新建configure包,然後在該包下新建WebSocketServerConfigure
配置類:
@Configuration
@EnableWebSocket
public class WebSocketServerConfigure implements WebSocketConfigurer {
@Autowired
private MyStringWebSocketHandler myStringWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myStringWebSocketHandler, "/connect").withSockJS();
}
}
@EnableWebSocket
用於開啟WebSocket相關功能,我們注入了上面建立的MyStringWebSocketHandler,並將其註冊到了WebSocketHandlerRegistry
。
上面程式碼的含義是,當客戶端通過/connect
url和服務端連線通訊時,使用MyStringWebSocketHandler
處理會話。withSockJS
的含義是,通訊的客戶端是通過SockJS實現的,下面會介紹到。
3.構建客戶端
SockJS是一個JS外掛,用於構建WebSocket,相容性好。
在resources目錄下新建static包,然後在該包下新建client.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket客戶端</title>
<script src="https://cdn.bootcss.com/sockjs-client/0.3.4/sockjs.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<style>
.jumbotron {
width: 100%;
}
#text {
height: 3rem;
font-size: 1rem;
line-height: 3rem;
margin: 1rem;
}
.btn {
margin-right: 5px;
}
#connect {
margin-left: 1rem;
}
#log {
margin: 1rem 0 0 1rem;
}
</style>
<div class="container">
<div class="row">
<div class="jumbotron">
<input type="text" placeholder="請輸入你想傳輸的內容" id="text" class="col-lg-12"/>
<input type="button" value="連線" class="btn btn-info" id="connect" onclick="connect()"/>
<input type="button" value="傳送" class="btn btn-success" id="sent" disabled="disabled" onclick="sent()"/>
<input type="button" value="斷開" class="btn btn-danger" id="disconnect" disabled="disabled"
onclick="disconnect()"/>
<div id="log">
<p>聊天記錄:</p>
</div>
</div>
</div>
</div>
<script type="text/javascript">
let text = document.querySelector('#text');
let connectBtn = document.querySelector("#connect");
let sentBtn = document.querySelector("#sent");
let disconnectBtn = document.querySelector("#disconnect");
let logDiv = document.querySelector("#log");
let ws = null;
function connect() {
let targetUri = "/connect";
ws = new SockJS(targetUri);
ws.onopen = function () {
setConnected(true);
log('和服務端連線成功!');
};
ws.onmessage = function (event) {
log('服務端說:' + event.data);
};
ws.onclose = function () {
setConnected(false);
log('和服務端斷開連線!')
}
}
function sent() {
if (ws != null) {
ws.send(text.value);
log('客戶端說:' + text.value);
} else {
log('請先建立連線!')
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
}
setConnected(false);
}
function log(value) {
let content = document.createElement('p');
content.innerHTML = value;
logDiv.appendChild(content);
text.value = '';
}
function setConnected(connected) {
connectBtn.disabled = connected;
disconnectBtn.disabled = !connected;
sentBtn.disabled = !connected;
}
</script>
</body>
</html>
html,css那些都不重要,重要的是我們引入了SockJS
庫。在connect()
方法中,我們通過new SockJS(/connect)
和上面的服務端建立了Socket通訊。SockJS
物件包含幾個常用的實用方法:
-
onopen
,和服務端講了連線後的回撥方法; -
onmessage
,服務端返回訊息時的回撥方法; -
onclose
,和服務端斷開連線的回撥方法; -
send
,傳送訊息給服務端; -
close
,斷開和服務端的連線。
上面的JS較為簡單,其他邏輯自己看看吧。
4.通訊測試
啟動專案,瀏覽器訪問:http://localhost:8080/client.html:
原始碼連線:https://github.com/wuyouzhuguli/SpringAll/tree/master/76.spring-boot-websocket-socketjs。
FROM:https://mrbird.cc/Spring-Boot%E6%95%B4%E5%90%88WebSocket.html****