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(); } @Override public 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/jquery@3.6.0/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/stompjs@2.3.3/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>
自己看代码吧 就不多解释了,剩下就是根据业务需要改改就可以.