springboot基礎環境,請參考springboot文檔
maven依賴javascript
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
代碼準備css
準備常量類html
//webSocket相關配置 //連接地址 public static String WEBSOCKETPATHPERFIX = "/ws-push"; public static String WEBSOCKETPATH = "/endpointWisely"; //消息代理路徑 public static String WEBSOCKETBROADCASTPATH = "/topic"; //前端發送給服務端請求地址 public static final String FORETOSERVERPATH = "/welcome"; //服務端生產地址,客戶端訂閱此地址以接收服務端生產的消息 public static final String PRODUCERPATH = "/topic/getResponse"; //點對點消息推送地址前綴 public static final String P2PPUSHBASEPATH = "/user"; //點對點消息推送地址後綴,最後的地址爲/user/用戶識別碼/msg public static final String P2PPUSHPATH = "/msg";
接收前端消息實體前端
public class WiselyMessage { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }
}
後臺發送消息實體java
private String responseMessage; public WiselyResponse(String responseMessage){ this.responseMessage = responseMessage; } public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; }
配置websocketjquery
@Configuration // @EnableWebSocketMessageBroker註解用於開啓使用STOMP協議來傳輸基於代理(MessageBroker)的消息,這時候控制器(controller)開始支持@MessageMapping,就像是使用@requestMapping同樣。 @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) { //註冊一個Stomp的節點(endpoint),並指定使用SockJS協議。 stompEndpointRegistry.addEndpoint(Constant.WEBSOCKETPATH).withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { //服務端發送消息給客戶端的域,多個用逗號隔開 registry.enableSimpleBroker(Constant.WEBSOCKETBROADCASTPATH, Constant.P2PPUSHBASEPATH); //定義一對一推送的時候前綴 registry.setUserDestinationPrefix(Constant.P2PPUSHBASEPATH); //定義websoket前綴 registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX); } }
serviceweb
@Service public class WebSocketService { @Autowired private SimpMessagingTemplate template; /** * 廣播 * 發給全部在線用戶 * @param msg */ public void sendMsg(WiselyResponse msg) { template.convertAndSend(Constant.PRODUCERPATH, msg); } /** * 發送給指定用戶 * @param users * @param msg */ public void send2Users(List<String> users, WiselyResponse msg) { users.forEach(userName -> { template.convertAndSendToUser(userName, Constant.P2PPUSHPATH, msg); }); } }
控制器spring
@Controller public class WsController { @Resource WebSocketService webSocketService; @MessageMapping(Constant.FORETOSERVERPATH)//@MessageMapping和@RequestMapping功能相似,用於設置URL映射地址,瀏覽器向服務器發起請求,須要經過該地址。 @SendTo(Constant.PRODUCERPATH)//若是服務器接受到了消息,就會對訂閱了@SendTo括號中的地址傳送消息。 public WiselyResponse say(WiselyMessage message) throws Exception { List<String> users = Lists.newArrayList(); users.add("d892bf12bf7d11e793b69c5c8e6f60fb");//此處寫死只是爲了方便測試,此值須要對應頁面中訂閱我的消息的userId webSocketService.send2Users(users, new WiselyResponse("admin hello")); return new WiselyResponse("Welcome, " + message.getName() + "!"); } }
頁面瀏覽器
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title>Spring Boot+WebSocket+廣播式</title> </head> <body onload="disconnect()"> <noscript><h2 style="color: #ff0000">貌似你的瀏覽器不支持websocket</h2> </noscript> <div> <div> <button id="connect" onclick="connect();">鏈接</button> <button id="disconnect" disabled="disabled" onclick="disconnect();">斷開鏈接</button> </div> <div id="conversationDiv"> <label>輸入你的名字</label><input type="text" id="name" /> <button id="sendName" onclick="sendName();">發送</button> <p id="response"></p> <p id="response1"></p> </div> </div> <!--<script th:src="@{sockjs.min.js}"></script> <script th:src="@{stomp.min.js}"></script> <script th:src="@{jquery.js}"></script>--> <script src="https://cdn.bootcss.com/sockjs-client/1.1.4/sockjs.min.js"> </script> <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.min.js"></script> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script th:inline="javascript"> var stompClient = null; //此值有服務端傳遞給前端,實現方式沒有要求 var userId = [[${userId}]]; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; $('#response').html(); } function connect() { var socket = new SockJS('/endpointWisely'); //1鏈接SockJS的endpoint是「endpointWisely」,與後臺代碼中註冊的endpoint要同樣。 stompClient = Stomp.over(socket);//2建立STOMP協議的webSocket客戶端。 stompClient.connect({}, function(frame) {//3鏈接webSocket的服務端。 setConnected(true); console.log('開始進行鏈接Connected: ' + frame); //4經過stompClient.subscribe()訂閱服務器的目標是'/topic/getResponse'發送過來的地址,與@SendTo中的地址對應。 stompClient.subscribe('/topic/getResponse', function(respnose){ showResponse(JSON.parse(respnose.body).responseMessage); }); //4經過stompClient.subscribe()訂閱服務器的目標是'/user/' + userId + '/msg'接收一對一的推送消息,其中userId由服務端傳遞過來,用於表示惟一的用戶,經過此值將消息精確推送給一個用戶 stompClient.subscribe('/user/' + userId + '/msg', function(respnose){ console.log(respnose); showResponse1(JSON.parse(respnose.body).responseMessage); }); }); } function disconnect() { if (stompClient != null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { var name = $('#name').val(); //經過stompClient.send()向地址爲"/welcome"的服務器地址發起請求,與@MessageMapping裏的地址對應。由於咱們配置了registry.setApplicationDestinationPrefixes(Constant.WEBSOCKETPATHPERFIX);因此須要增長前綴/ws-push/ stompClient.send("/ws-push/welcome", {}, JSON.stringify({ 'name': name })); } function showResponse(message) { var response = $("#response"); response.html(message); } function showResponse1(message) { var response = $("#response1"); response.html(message); } </script> </body> </html>
測試springboot
點擊鏈接控制檯輸出
表示鏈接成功而且訂閱了兩個地址
此時在文本框內輸入任意值
結果如圖所示則表明成功
控制檯中顯示依次爲,發送信息,目標長度內容
此時服務端控制器接收到請求
同時給指定用戶發送了消息,因此控制檯接收到消息
同時由於控制器有註解@SendTo因此會向@SendTo的地址廣播消息,客戶端訂閱了廣播地址全部控制檯顯示接收了消息