springboot + websocket 實現聊天室
阿新 • • 發佈:2021-07-28
1.前言
實現聊天室有很多種方式 netty, websocket等,我們這裡直接使用websocket技術,websocket是一種伺服器向客戶端傳送資訊的技術,而不是傳統的servlet客戶端傳送請求,然後伺服器給出響應.
現在比較流行的框架是springboot,而且spring官方也支援websocket,這裡借鑑了spring的官網文件,不排除以後技術會發生變化.
2.實現
2.1依賴
implementation 'org.springframework.boot:spring-boot-starter-websocket' testImplementation'org.springframework.boot:spring-boot-starter-test' implementation 'org.webjars:webjars-locator-core' implementation 'org.webjars:sockjs-client:1.0.2' implementation 'org.webjars:stomp-websocket:2.3.3' implementation 'org.webjars:bootstrap:3.3.7' implementation 'org.webjars:jquery:3.1.1-1'
2.2配置檔案
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/gs-guide-websocket").withSockJS(); } @Overridepublic void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic","/user"); registry.setApplicationDestinationPrefixes("/app"); } }
setApplicationDestinationPrefixes 定義了websocket應用的訪問字首,
addEndpoint 定義了socketjs的連線,
enableSimpleBroker 定義了啟用的廣播路徑,如果這裡不加上路徑的話,websocket無法廣播,也就是不法向客戶端傳送訊息
2.3訊息類
public class HelloMessage { private String name; public HelloMessage() { super(); } public HelloMessage(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Greeting { private String content; public Greeting() { super(); // TODO Auto-generated constructor stub } public Greeting(String content) { super(); this.content = content; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
沒什麼好說的,資訊載體類
2.4controller
@Controller public class GreetingController { @Autowired private SimpMessagingTemplate simpMessagingTemplate; @MessageMapping("/hello") //@SendTo //@SendToUser public Greeting greeting(HelloMessage message) throws InterruptedException { Greeting result = new Greeting("Hello,"+HtmlUtils.htmlEscape(message.getName())); TimeUnit.SECONDS.sleep(1L); simpMessagingTemplate.convertAndSendToUser("bob", "/queue/position-updates", result); return new Greeting("Hello,"+HtmlUtils.htmlEscape(message.getName())); } }
我們可以使用 SendTo 定義返回路徑,也可以使用 SendToUser 定義返回的使用者,這些都是使用註解定義的,如果想要更靈活的可以使用 SimpMessagingTemplate 這個類來廣播訊息.
2.5 前端實現
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <noscript> <h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!</h2> </noscript> <div id="main-content" class="container"> <div class="row"> <div class="col-md-6"> <form class="form-inline"> <div class="form-group"> <label for="connect">WebSocket connection:</label> <button id="connect" class="btn btn-default" type="submit">Connect</button> <button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect </button> </div> </form> </div> <div class="col-md-6"> <form class="form-inline"> <div class="form-group"> <label for="name">What is your name?</label> <input type="text" id="name" class="form-control" placeholder="Your name here..."> </div> <button id="send" class="btn btn-default" type="submit">Send</button> </form> </div> </div> <div class="row"> <div class="col-md-12"> <table id="conversation" class="table table-striped"> <thead> <tr> <th>Greetings</th> </tr> </thead> <tbody id="greetings"> </tbody> </table> </div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.js"></script> <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/stomp.min.js"></script> <script> var stompClient = null; function setConnected(connected) { $("#connect").prop("disabled", connected); $("#disconnect").prop("disabled", !connected); if (connected) { $("#conversation").show(); } else { $("#conversation").hide(); } $("#greetings").html(""); } function connect() { var socket = new SockJS('/gs-guide-websocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/user/bob/queue/position-updates', function (greeting) { console.log(greeting) showGreeting(JSON.parse(greeting.body).content); }); }); } function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({ 'name': $("#name").val() })); } function showGreeting(message) { $("#greetings").append("<tr><td>" + message + "</td></tr>"); } $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $("#connect").click(function () { connect(); }); $("#disconnect").click(function () { disconnect(); }); $("#send").click(function () { sendName(); }); }); </script> </body> </html>
自己看程式碼吧 就不多解釋了,剩下就是根據業務需要改改就可以.