項目中碰到從後臺實時接收通知然後語音播放的需求,以前項目中調用過別人寫的websocket接口,這次自己寫了一下,分享下:
1.依賴的引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.5.3.RELEASE</version>
<type>pom</type>
</dependency>
以上是springboot工程的引入,如果是普通的war包部署tomcat可以如下配置:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
2.聲明註冊使用@ServerEndpoint 註解,
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
} }
3.寫服務類
@ServerEndpoint(value = "/websocket") //接受websocket請求路徑 @Component //註冊到spring容器中 public class AlarmWebSocket { //保存所有在線socket連接 private static Map<String,AlarmWebSocket> webSocketMap = new LinkedHashMap<>(); //記錄當前在線數目 private static int count=0; //當前連接(每個websocket連入都會創建一個MyWebSocket實例 private Session session; private Logger log = LoggerFactory.getLogger(this.getClass()); //處理連接建立 @OnOpen public void onOpen(Session session){ this.session=session; webSocketMap.put(session.getId(),this); addCount(); log.info("新的連接加入:{}",session.getId()); } //接受消息 @OnMessage public void onMessage(String message,Session session){ log.info("收到客戶端{}消息:{}",session.getId(),message); try{ this.sendMessage("收到消息:"+message); }catch (Exception e){ e.printStackTrace(); } } //處理錯誤 @OnError public void onError(Throwable error,Session session){ log.info("發生錯誤{},{}",session.getId(),error.getMessage()); } //處理連接關閉 @OnClose public void onClose(){ webSocketMap.remove(this.session.getId()); reduceCount(); log.info("連接關閉:{}",this.session.getId()); } //羣發消息 //發送出去消息 public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message);//這裏可以寫死字符串測試 } //廣播消息 public static void broadcast(String message){ AlarmWebSocket.webSocketMap.forEach((k,v)->{ try{ v.sendMessage(message); }catch (Exception e){ } }); } //獲取在線連接數目 public static int getCount(){ return count; } //操作count,使用synchronized確保線程安全 public static synchronized void addCount(){ AlarmWebSocket.count++; } public static synchronized void reduceCount(){ AlarmWebSocket.count--; } }
4.前端建立連接及發送消息測試
<html>
<head> <title>websocket測試</title> <meta charset="utf-8" /> </head>
<body>
<button οnclick="sendMessage()">測試</button>
<script>
let socket = new WebSocket("ws://localhost:8080/websocket");
socket.onerror = err => { console.log(err); };
socket.onopen = event => { console.log(event); };
socket.onmessage = mess => { console.log(mess); };
socket.onclose = () => { console.log("連接關閉"); };
function sendMessage() {
if (socket.readyState === 1) socket.send("這是向後臺發送的測試數據");
else alert("還沒成功建立websocket連接"); }
</script> </body> </html>
5.如果前臺沒問題,後臺測試發送給前臺消息
@RestController
public class TestController {
@GetMapping("/broadcast")
public void broadcast(){ MyWebSocket.broadcast();
} }
在瀏覽器F12打開前端日誌,觀察websocket狀態,打印:
Event {isTrusted: true, type: "open", target: WebSocket, currentTarget: WebSocket, eventPhase: 2, …}
type狀態是open表示成功建立websocket連接,後臺發送給前端消息,也可以打印出日誌