花了20分鐘,給女朋友們寫了一個web版群聊程式
WebSocket詳解
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連線上進行全雙工通訊的協議。
WebSocket 使得客戶端和伺服器之間的資料交換變得更加簡單,允許服務端主動向客戶端推送資料。在 WebSocket API 中,瀏覽器和伺服器只需要完成一次握手,兩者之間就直接可以建立永續性的連線,並進行雙向資料傳輸。可以說WebSocket的出現,使得瀏覽器具備了實時雙向通訊的能力
在 WebSocket API 中,瀏覽器和伺服器只需要做一個握手的動作,然後,瀏覽器和伺服器之間就形成了一條快速通道。兩者之間就直接可以資料互相傳送。
原來為了實現推送,很多公司用的是Ajax 輪詢,即按照特定的時間間隔,由瀏覽器對伺服器發出HTTP請求,然後由伺服器返回最新的資料給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向伺服器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的資料可能只是很小的一部分,顯然這樣會浪費很多的頻寬等資源。而websocket就可以解決這些問題。
在Spring Boot中使用WebSocket
1.pom檔案增加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.增加配置
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.Java程式碼
@Component
@ServerEndpoint("/websocket")
public class WebSocketServerController {
// 收到訊息呼叫的方法
@OnMessage
public void onMessage(String message) {
System.out.println("收到的訊息為 " + message);
}
// 建立連線呼叫的方法
@OnOpen
public void onOpen() {
System.out.println("Client connected");
}
// 關閉連線呼叫的方法
@OnClose
public void onClose() {
System.out.println("Connection closed");
}
// 傳輸訊息錯誤呼叫的方法
@OnError
public void OnError(Throwable error) {
System.out.println("Connection error");
}
}
4.前端程式碼
<!DOCTYPE html>
<html>
<head>
<title>Testing websockets</title>
</head>
<body>
<div>
<textarea rows="3" cols="20" id="content"></textarea>
<br>
<input type="submit" value="Start" onclick="start()" />
</div>
<div id="messages"></div>
<script type="text/javascript">
var webSocket =
new WebSocket('ws://localhost:8080/websocket');
webSocket.onerror = function(event) {
onError(event)
};
webSocket.onopen = function(event) {
onOpen(event)
};
webSocket.onmessage = function(event) {
onMessage(event)
};
webSocket.onclose = function(event) {
onClose(event)
};
function onMessage(event) {
document.getElementById('messages').innerHTML
+= '<br />' + event.data;
}
function onOpen(event) {
document.getElementById('messages').innerHTML
= 'Connection established';
}
function onError(event) {
alert(event);
}
function onClose(event) {
alert(event);
}
function start() {
var text = document.getElementById('content').value;
webSocket.send(text);
}
</script>
</body>
</html>
所以你看websocket其實很簡單,前後端各寫4個事件方法就行了(當然你也可以省略一些方法)
1.建立連線
2.收到訊息
3.傳輸訊息失敗
4.關閉連線
事件和具體會話關聯
如果事件想和具體會話關聯,方法上只要加Session引數就行(4種事件型別的方法上都可加)
舉個例子,直接將使用者傳送給服務端的話再返回給客戶端
// 收到訊息呼叫的方法
@OnMessage
public void onMessage(Session session, String message) {
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
傳遞引數
方法上加@PathParam引數即可
@Component
@ServerEndpoint("/websocket/{sid}")
public class WebSocketServerController
@OnOpen
public void onOpen(@PathParam("sid") String sid) {
System.out.println("Client connected");
}
實現一個線上群聊
後端介面
@Slf4j
@Component
@ServerEndpoint("/groupChat/{sid}/{username}")
public class GroupChatController {
// 儲存 組id->組成員 的對映關係
private static ConcurrentHashMap<String, List<Session>> groupMemberInfoMap = new ConcurrentHashMap<>();
// 收到訊息呼叫的方法,群成員傳送訊息
@OnMessage
public void onMessage(@PathParam("sid") String sid,
@PathParam("username") String username, String message) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
// 先一個群組內的成員傳送訊息
sessionList.forEach(item -> {
try {
String text = username + ": " + message;
item.getBasicRemote().sendText(text);
} catch (IOException e) {
e.printStackTrace();
}
});
}
// 建立連線呼叫的方法,群成員加入
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
if (sessionList == null) {
sessionList = new ArrayList<>();
groupMemberInfoMap.put(sid,sessionList);
}
sessionList.add(session);
log.info("Connection connected");
log.info("sid: {}, sessionList size: {}", sid, sessionList.size());
}
// 關閉連線呼叫的方法,群成員退出
@OnClose
public void onClose(Session session, @PathParam("sid") String sid) {
List<Session> sessionList = groupMemberInfoMap.get(sid);
sessionList.remove(session);
log.info("Connection closed");
log.info("sid: {}, sessionList size: {}", sid, sessionList.size());
}
// 傳輸訊息錯誤呼叫的方法
@OnError
public void OnError(Throwable error) {
log.info("Connection error");
}
}
前端程式碼很簡單,放github了
地址為:https://github.com/erlieStar/spring-boot-websocket
下面來看效果
注意先連線,後傳送
線上開房地址:
http://www.javashitang.com:8090/
歡迎關注
參考部落格
好文
[1]https://blog.csdn.net/moshowgame/article/details/80275084
[2]https://www.jianshu.com/p/d79bf8174196
[3]https://www.byteslounge.com/tutorials/java-ee-html5-websocket-example
一個群聊程式
[4]https://blog.csdn.net/moshowgame/article/details/80275084
相關文章
- 女朋友想減肥,程式設計師花了三天寫了個卡路里計數器程式設計師
- 我花了一夜用資料結構給女朋友寫個H5走迷宮遊戲資料結構H5遊戲
- 太熱了!程式猿給女朋友做了個智慧小風扇
- 3 分鐘寫個 web 人臉識別登入,這樣式愛了Web
- 前端還能這麼玩?(女朋友生日,用前端寫了一個好玩的送給了她,高興壞了)前端
- 【緊急情況】:回宿舍放下書包的我,花了20分鐘敲了一個搶購指令碼指令碼
- 30分鐘編寫一個Flask應用Flask
- 給喜歡的女孩子寫了一段python程式碼,不用我表白,就成我女朋友了Python
- 面試官讓我5分鐘內寫一個搶紅包程式,我和他說了半小時原理!面試
- 20行程式碼寫一個簡單 Blazor 時鐘元件行程Blazor元件
- 花了一整天寫了個下載markdown圖片到本地的庫?
- 2 分鐘,教你用 Serverless 每天給女朋友自動發土味情話Server
- 只需 5 分鐘,教你如何編寫並執行一個 Rust + WebAssembly 程式RustWeb
- 天天寫業務程式碼,我給擼了一個業務處理框架框架
- 寫給創業公司的程式猿們創業
- 使用Netty三分鐘手寫一個RPCNettyRPC
- 用 react+moox 五分鐘寫一個 todomvc 應用ReactMVC
- 3分鐘短文:Laravel寫個命令列,你就是下一個Geek!Laravel命令列
- 十分鐘寫個RPC框架RPC框架
- 一個老程式設計師的程式設計之路,寫給年輕的程式設計師們程式設計師
- [BUG]Appium1.9.1 這個問題竟然花了我5分鐘進行定位APP
- 寫給程式猿們的互動設計
- 如果老婆和女朋友她們是程式
- Serverless實戰——2分鐘,教你用Serverless每天給女朋友自動發土味情話Server
- 如何在 20 分鐘內給你的 K8s PaaS 上線一個新功能?K8S
- 一個妹子寫給程式猿男友的情書
- 寫給程式設計師:我們這一代不是汽車工人程式設計師
- 我用開源工具給女朋友寫道歉信!開源工具
- 寫給那些IT的新人們
- web app 一分鐘適配 iPhone XWebAPPiPhone
- 一個會做飯的程式設計師如何每天給女朋友帶不同的便當?程式設計師
- 花了一個星期,我終於把RPC框架整明白了!RPC框架
- 改寫一個要跑5小時的SQL成1分鐘SQL
- Flask一分鐘Mock一個APIFlaskMockAPI
- 用 actix-Web 2.0-α 寫了一個小工具Web
- 我花了 24 小時,“重新"實現了一版ant design pro
- 我們開源了一個輕量的 Web IDE UI 框架WebIDEUI框架
- 仿寫一個簡單的微信小程式(番茄鬧鐘)微信小程式