前言
利用websocket實作與網頁互動,消息推送點對點消息推送,還有一種springboot的實作,下次再說
配置:
package com.zoo.websocket.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @author: 謝飛
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
package com.zoo.websocket.server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @author: 謝飛
*/
@Slf4j
@ServerEndpoint("/websocket/server/{sid}")
@Component
public class WebSocketServer {
//靜态變量,用來記錄目前線上連接配接數。應該把它設計成線程安全的。
private static int onlineCount = 0;
//concurrent包的線程安全Set,用來存放每個用戶端對應的MyWebSocket對象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();
//與某個用戶端的連接配接會話,需要通過它來給用戶端發送資料
private Session session;
//接收sid
private String sid = "";
/**
* 連接配接建立成功調用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
//加入set中
webSocketSet.add(this);
//線上數加1
addOnlineCount();
log.info("有新視窗開始監聽:" + sid + ",目前線上人數為" + getOnlineCount());
this.sid = sid;
try {
sendMessage("連接配接成功");
} catch (IOException e) {
log.error("websocket IO異常");
}
}
/**
* 連接配接關閉調用的方法
*/
@OnClose
public void onClose() {
//從set中删除
webSocketSet.remove(this);
//線上數減1
subOnlineCount();
log.info("有一連接配接關閉!目前線上人數為" + getOnlineCount());
}
/**
* 收到用戶端消息後調用的方法
*
* @param message 用戶端發送過來的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到來自視窗" + sid + "的資訊:" + message);
//群發消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 發生錯誤
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("發生錯誤");
error.printStackTrace();
}
/**
* 實作伺服器主動推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
//this.session.getAsyncRemote().sendText(message);
}
/**
* 群發自定義消息
*/
public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
log.info("推送消息到視窗" + sid + ",推送内容:" + message);
for (WebSocketServer item : webSocketSet) {
try {
//這裡可以設定隻推送給這個sid的,為null則全部推送
if (sid == null) {
item.sendMessage(message);
} else if (item.sid.equals(sid)) {
item.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
package com.zoo.websocket.controller;
import com.zoo.base.bean.Resp;
import com.zoo.websocket.server.WebSocketServer;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
/**
* @author: 謝飛
*/
@Controller
public class TestController {
@GetMapping("/")
public String index(String sid, Model model) {
if (StringUtils.isBlank(sid)) {
model.addAttribute("websocketUrl", "ws://localhost:3000/websocket/server/null");
} else {
model.addAttribute("websocketUrl", "ws://localhost:3000/websocket/server/" + sid);
}
return "index";
}
//推送資料接口
@ResponseBody
@RequestMapping("/push")
public Resp pushToWeb(String sid, String message) {
try {
WebSocketServer.sendInfo(message, sid);
} catch (IOException e) {
e.printStackTrace();
return Resp.fail(sid + "#" + e.getMessage());
}
return Resp.ok(sid);
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input id="websocketUrl" type="hidden" th:value="${websocketUrl}"/>
</body>
<script>
var socket;
if (typeof (WebSocket) == "undefined") {
console.log("您的浏覽器不支援WebSocket");
} else {
console.log("您的浏覽器支援WebSocket");
//實作化WebSocket對象,指定要連接配接的伺服器位址與端口 建立連接配接
socket = new WebSocket(document.getElementById("websocketUrl").value);
//打開事件
socket.onopen = function () {
console.log("Socket 已打開");
//socket.send("這是來自用戶端的消息" + location.href + new Date());
};
//獲得消息事件
socket.onmessage = function (msg) {
console.log(msg.data);
//發現消息進入,開始處理前端觸發邏輯
};
//關閉事件
socket.onclose = function () {
console.log("Socket已關閉");
};
//發生了錯誤事件
socket.onerror = function () {
alert("Socket發生了錯誤");
//此時可以嘗試重新整理頁面
}
}
</script>
</html>