本文記錄在SpringBoot中使用WebSocket。html
WebSocket是基於TCP協議的一種網絡協議,它實現了瀏覽器與服務器全雙工通訊,支持客戶端和服務端之間相互發送信息。在有WebSocket以前,若是服務端數據發生了改變,客戶端想知道的話,只能採用定時輪詢的方式去服務端獲取,這種方式很大程度上增大了服務器端的壓力,有了WebSocket以後,若是服務端數據發生改變,能夠當即通知客戶端,客戶端就不用輪詢去換取,下降了服務器的壓力。目前主流的瀏覽器都已經支持WebSocket協議了。
WebSocket使用ws和wss做資源標誌符,它們兩個相似於http和https,wss是使用TSL的ws。主要有4個事件:
onopen 建立鏈接時觸發
onclose 鏈接斷開時觸發
onmessage 接收到信息時觸發
onerror 通信異常時觸發java
SpringBoot對WebSocket也作了支持,須要使用的話引入依賴所須要的包spring-boot-starter-websocket就能夠了。咱們利用它能夠雙向通訊的特性來實現一個簡單的聊天室功能。主要功能以下jquery
1 用戶在瀏覽器端進入聊天室(建立WebSocket鏈接);web
2 用戶端發送消息到服務端(客戶端像服務端發信息);spring
3 服務端將消息轉發到客戶端(服務端向客戶端發信息);瀏覽器
4 用戶退出聊天室(斷開WebSocket鏈接)。服務器
修改pom.xml文件,引入WebSocket的支持websocket
<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>
修改application.properties文件,配置服務相關信息網絡
server.port=8090
server.servlet.context-path=/websocket
要使用WebSocket,咱們須要在啓動來開啓對WebSocket的支持功能,使用@EnableWebSocket註解session
@SpringBootApplication
@EnableWebSocket
public class WebSocketApplication {
public static void main(String[] args) {
SpringApplication.run(WebSocketApplication.class, args);
}
/**
* 初始化Bean,它會自動註冊使用了 @ServerEndpoint 註解聲明的 WebSocket endpoint
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
聊天時,咱們須要知道有哪些用戶在線,因此咱們建立一個工具類來記錄在線用戶和實現服務端向客戶端發送消息
public class WebSocketUtil {
/**
* 模擬存儲 在線用戶
*/
public static final Map<String, Session> USERS_ONLINE = new ConcurrentHashMap<>();
/**
* 向全部在線用戶發送消息(遍歷 向每個用戶發送)
* @param message
*/
public static void sendMessageToAllOnlineUser(String message){
USERS_ONLINE.forEach((username, Session) -> sendMessage(Session, message));
}
/**
* 向指定用戶發送消息
* @param session 用戶session
* @param message 發送消息內容
*/
private static void sendMessage(Session session, String message) {
if (session == null) {
return;
}
final RemoteEndpoint.Basic basic = session.getBasicRemote();
if (basic == null) {
return;
}
try {
basic.sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
服務端類,使用@ServerEndpoint("")說明服務端監聽此地址的消息
@Controller
@ServerEndpoint("/chat/{username}") //說明建立websocket的endpoint
public class ChatServerEndpoint {
/**
* 訪問聊天室頁面
* @return
*/
@GetMapping("/chatPage")
public String chatPage(){
return "chat.html";
}
}
WebSocket有4個事件,咱們對每一個事件作監聽,使用對應的註解便可實現監聽
onopen 在鏈接建立(用戶進入聊天室)時觸發
@OnOpen
public void openSession(@PathParam("username") String username, Session session){
//存儲用戶
WebSocketUtil.USERS_ONLINE.put(username, session);
//向全部在線用戶發送用戶上線通知消息
String message = "["+username+"]進入聊天室";
System.out.println(message);
WebSocketUtil.sendMessageToAllOnlineUser(message);
}
onclose 在鏈接斷開(用戶離開聊天室)時觸發
@OnClose
public void closeSession(@PathParam("username") String username, Session session){
//刪除用戶
WebSocketUtil.USERS_ONLINE.remove(username);
//向全部在線用戶發送用戶下線通知消息
String message = "["+username+"]離開了聊天室";
System.out.println(message);
WebSocketUtil.sendMessageToAllOnlineUser(message);
//下線後關閉session
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
onmessage 在接收到消息時觸發
@OnMessage
public void onMessage(@PathParam("username") String username, String message){
//向聊天室中的人發送消息
message = "["+username+"]:" + message;
System.out.println(message);
WebSocketUtil.sendMessageToAllOnlineUser(message);
}
orerror 在鏈接發生異常時觸發
@OnError
public void sessionError(Session session, Throwable throwable){
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("WebSocket鏈接發生異常,message:"+throwable.getMessage());
}
聊天室頁面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery-1.9.1.min.js"></script>
</head>
<body>
<table>
<tr><td>
<label for="messageArea">聊天信息:</label><textarea id="messageArea" cols="50" rows="30"></textarea></br>
</td></tr>
<tr><td>
<label for="username">用 戶 名:</label><input type="text" id="username" ></br>
</td></tr>
<tr><td>
<input type="button" id="joinRoomBtn" value="進入聊天室" />
<input type="button" id="leaveRoomBtn" value="離開聊天室" /></br>
</td></tr>
<tr><td>
<label for="sendMessage">輸入消息:</label><textarea id="sendMessage" cols="50" rows="3"></textarea></br>
</td></tr>
<tr><td>
<input type="button" id="sendBtn" value="發送消息" />
</td></tr>
</table>
</body>
</html>
WebSocket客戶端鏈接服務端及相關事件方法
<script> $(function(){ var webSocket; var url = 'ws://localhost:8090/websocket/chat/'; //進入聊天室 $('#joinRoomBtn').click(function(){ var username = $('#username').val(); webSocket = new WebSocket(url+username); webSocket.onopen = function (){ console.log('webSocket鏈接建立。。。'); } webSocket.onclose = function(){ $('#messageArea').append('['+username+']離開了聊天室\n'); } webSocket.onmessage = function(event){ $('#messageArea').append(event.data + '\n'); } webSocket.onerror = function (event) {
console.log('webSocket鏈接異常。。。'); } }); //退出聊天室 $('#leaveRoomBtn').click(function(){ if(webSocket){ //關閉鏈接 webSocket.close(); } }); //發送消息 $('#sendBtn').click(function(){ var msg = $('#sendMessage').val(); webSocket.send(msg); $('#sendMessage').val(''); }); }); </script>
啓動項目,訪問聊天室頁面,先輸入用戶名加入聊天室,再發送消息及退出聊天室,爲了效果,打開兩個瀏覽器,以下圖