springboot下的websocket訊息推送
阿新 • • 發佈:2019-02-03
websocket是客戶端和服務端之間的通訊,所以我們需要實現websocket的服務端和客戶端,而這裡客戶端我們寫到Html的前端中。websocket的開發需要進行以下幾個步驟:
1.引入依賴<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.對websocket進行配置
@Component
public class WebSocketConfig {
//把你要例項化的物件轉化成一個Bean,放在IoC容器中
@Bean
public ServerEndpointExporter serverEndpointExporter () {
return new ServerEndpointExporter();
}
}
注意:上面這種配置有個缺點,就是服務端的類裡面無法使用@Value或@Autowired之類的Spring注入。修改的方法,痛過百度,在後面有寫到。
3.編寫服務端實現類。
websocket與普通controller不太一樣,但也不是service。這裡,筆者把它寫在service目錄下
該類應該有一下幾個功能。@OnOpen有新的連線。@OnClose連線關閉。@OnMeesage收到資訊。sendMessage傳送資訊。
package com.wechat.order.service; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; @Component @ServerEndpoint("/webSocket")//呼叫websocket的url @Slf4j public class WebSocket { private static int onlineCount = 0;//記錄總連線數 //定義一個websocket的容器,用來儲存這些session private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();//注意這裡不能直接使用Set集合。 private Session session; /** * 有新的連線 * @param session * @throws IOException */ @OnOpen public void onOpen(Session session) throws IOException{ this.session = session; webSocketSet.add(this); incrOnlineCount();//連線數+1 log.info("【websocket訊息】有新的連線,當前總連線數: {}", getOnlineCount()); } /** * 連線關閉 * @throws IOException */ @OnClose public void onClose() throws IOException{ webSocketSet.remove(this); decOnlineCount();//連線數-1 log.info("【websocket訊息】有連線斷開,當前總連線數:: {}", getOnlineCount()); } /** * 收到資訊 * @param message 收到的資訊內容 * @param session * @throws IOException */ @OnMessage public void onMessage(String message, Session session) throws IOException { log.info("【websocket訊息】收到客戶端發來的訊息: {}", message); // broadcast received message for(WebSocket item : webSocketSet){ item.sendMessage(message); } } /** * 使用廣播發送訊息 * @param message */ public void sendMessage(String message) { log.info("【websocket訊息】廣播訊息: {}", message); for(WebSocket webSocket : webSocketSet){ //傳送訊息這類不是特別重要,不影響程式執行的異常可以直接try,catch try { webSocket.session.getBasicRemote().sendText(message); }catch (Exception e) { log.error("websocket訊息】廣播訊息異常: {}", e.getStackTrace()); } } } /** * 當前連線數 * @return */ public static synchronized int getOnlineCount(){ return WebSocket.onlineCount; } /** * 連線記錄+1 */ public static synchronized void incrOnlineCount(){ WebSocket.onlineCount++; } /** * 連線記錄-1 */ public static synchronized void decOnlineCount(){ WebSocket.onlineCount--; } }
4.客戶端,這裡使用html的js和vue來實現
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My WebSocket</title>
<script src="js/vue.js"></script>
</head>
<body>
Welcome To My WebSocket.<br/><br/>
<div id="ws">
<input id="text" type="text"/>
<button onclick="sendMsg()">Send</button>
<button onclick="closeWS()" :disabled="!opened">Close</button>
<button onclick="openWS()" :disabled="opened">Open</button>
<div v-html="msg"></div>
</div>
</body>
<script type="text/javascript">
var websocket = null;
var wsVue = new Vue({
el: '#ws',
data: {
msg: "welcome to my websocket...<br/>",
opened: false
},
mounted: function(){
initWs();
}
});
function initWs() {
//check if your browser supports WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/webSocket");
}
else {
alert('Sorry, websocket not supported by your browser.')
}
//Error callback
websocket.onerror = function () {
setMessageContent("error!");
wsVue.opened = false;
};
//socket opened callback
websocket.onopen = function (event) {
setMessageContent("websocket opened");
wsVue.opened = true;
}
//message received callback
websocket.onmessage = function (event) {
setMessageContent(event.data);
}
//socket closed callback
websocket.onclose = function () {
setMessageContent("websocket closed");
wsVue.opened = false;
}
//when browser window closed, close the socket, to prevent server exception
window.onbeforeunload = function () {
websocket.close();
}
}
//update message to vue and then in div
function setMessageContent(content) {
wsVue.msg += content + '<br/>';
}
//click to close the websocket
function closeWS() {
websocket.close();
wsVue.opened = false;
}
//click to open the websocket
function openWS() {
initWs();
}
//click to send message
function sendMsg() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</body>
</html>
下面講解配置websocket的第二種方法:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(CmdHandler(), "/webSocket"); //url和handler的mapping
}
@Bean
public WebSocketHandler WebSocket() {
return new WebSocket();
}
}