WebSocket初识:实现消息的发送
目标:
1.用户打开一个网页,点击连接后可以发送消息,展示在消息推送的位置,其他在线的用户也能看得到
2.admin页面访问能发送消息,index页面访问只能看消息不能发送消息
(一).网页:
admin.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <head> <!-- pom.xml使用了webjars声明了版本号,所以这里导入不需要版本号 --> <title>Hello WebSocket</title> <link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link href="/v1/main.css" rel="stylesheet"> <script src="/webjars/jquery/jquery.min.js"></script> <script src="/webjars/sockjs-client/sockjs.min.js"></script> <script src="/webjars/stomp-websocket/stomp.min.js"></script> <script src="/v1/app.js"></script> </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">建立连接通道:</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">发布新公告</label> <input type="text" id="content" class="form-control" placeholder="请输入..."> </div> <button id="send" class="btn btn-default" type="submit">发布</button> </form> </div> </div> <div class="row"> <div class="col-md-12"> <table id="conversation" class="table table-striped"> <thead> <tr> <th>游戏公告内容</th> </tr> </thead> <tbody id="notice"> <!-- 内容展示 --> </tbody> </table> </div> </div> </div> </body> </html>
index.html
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <head> <title>Hello WebSocket</title> <link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link href="/v1/main.css" rel="stylesheet"> <script src="/webjars/jquery/jquery.min.js"></script> <script src="/webjars/sockjs-client/sockjs.min.js"></script> <script src="/webjars/stomp-websocket/stomp.min.js"></script> <script src="/v1/app.js"></script> </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">建立连接通道:</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">发布新公告</label> <input type="text" id="content" class="form-control" placeholder="请输入..."> </div> <button id="send" class="btn btn-default" type="submit">发布</button> </form> </div> --> </div> <div class="row"> <div class="col-md-12"> <table id="conversation" class="table table-striped"> <thead> <tr> <th>游戏公告内容</th> </tr> </thead> <tbody id="notice"> <!-- 内容展示 --> </tbody> </table> </div> </div> </div> </body> </html>
(二).app.js:点击实现和方法实现
整个文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var stompClient = null; /** * 建立连接 * @param connected */ function setConnected(connected) { $("#connect").prop("disabled", connected); $("#disconnect").prop("disabled", !connected); //连接connected之后展示游戏公告列表,否则隐藏列表 if (connected) { $("#conversation").show(); } else { $("#conversation").hide(); } $("#notice").html(""); } /** * 连接,回调 */ function connect() { /** * 连接上【端点】,在WebSocketConfig配置得一个端点 * 连接了的就调用展示公告的方法 */ var socket = new SockJS('/endpoint-websocket'); /** * 用stom进行包装,规范协议 */ stompClient = Stomp.over(socket); /** * client.connect(headers, connectCallback, errorCallback); * {} 回调 失败回调 */ stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); /** * 【订阅】: * 1.STOMP 客户端要想接收来自服务器推送的消息,必须先订阅相应的URL,即发送一个【SUBSCRIBE 帧】,然后才能不断接收来自服务器的推送消息; * 2.订阅和接收消息通过 subscribe() 方法实现:var subscription = subscribe(destination url, callback[, headers]) * 1.destination url 为服务器【@SendTo】匹配的 URL,字符串; * 2.callback 为每次收到服务器推送的消息时的回调方法,该方法包含参数 message; * 3.headers 为附加的headers,JavaScript 对象。 * 4.该方法返回一个包含了id属性的 JavaScript 对象,可作为 unsubscribe() 【取消订阅】方法的参数; * subscription.unsubscribe(); */ /** * result即是响应结果 */ stompClient.subscribe('/topic/game_chat', function (result) { console.info(result) showContent(JSON.parse(result.body)); }); }); } /** * 断开连接 */ function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } setConnected(false); } /** * 发送消息:调用接口 */ function sendName() { /** * 1.连接成功后,客户端可使用 send() 方法向服务器发送信息: * 2.client.send(destination url[, headers[, body]]); * 1.destination url 为服务器 controller中【@MessageMapping】中匹配的URL,字符串,必须参数; * 2.headers 为发送信息的header,JavaScript 对象,可选参数; * 3.body 为发送信息的 body,字符串,可选参数; * 4.发送的消息可被【订阅】了的客户端接收展示 */ stompClient.send("/app/v1/chat", {}, JSON.stringify({'content': $("#content").val()})); } /** * 展示消息 * @param body */ function showContent(body) { /** * 展示内容+日期时间 */ $("#notice").append("<tr><td>" + body.content + "</td> <td>"+new Date(body.time).toLocaleString()+"</td></tr>"); } /** * $(function () {js代码} * 页面渲染完毕才执行,事件就能够成功绑定。 * 页面渲染完成后,触发什么事件就执行什么事件 */ $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $( "#connect" ).click(function() { connect(); }); $( "#disconnect" ).click(function() { disconnect(); }); $( "#send" ).click(function() { sendName(); }); });
分析:
1).页面加载完成后执行方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * $(function () {js代码} * 页面渲染完毕才执行,事件就能够成功绑定。 * 页面渲染完成后,触发什么事件就执行什么事件 */ $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $( "#connect" ).click(function() { connect(); }); $( "#disconnect" ).click(function() { disconnect(); }); $( "#send" ).click(function() { sendName(); }); });
2).点击连接调用方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 连接,回调 */ function connect() { /** * 连接上【端点】,在WebSocketConfig配置得一个端点 * 连接了的就调用展示公告的方法 */ var socket = new SockJS('/endpoint-websocket'); /** * 用stom进行包装,规范协议 */ stompClient = Stomp.over(socket); /** * client.connect(headers, connectCallback, errorCallback); * {} 回调 失败回调 */ stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); /** * 【订阅】: * 1.STOMP 客户端要想接收来自服务器推送的消息,必须先订阅相应的URL,即发送一个【SUBSCRIBE 帧】,然后才能不断接收来自服务器的推送消息; * 2.订阅和接收消息通过 subscribe() 方法实现:var subscription = subscribe(destination url, callback[, headers]) * 1.destination url 为服务器【@SendTo】匹配的 URL,字符串; * 2.callback 为每次收到服务器推送的消息时的回调方法,该方法包含参数 message; * 3.headers 为附加的headers,JavaScript 对象。 * 4.该方法返回一个包含了id属性的 JavaScript 对象,可作为 unsubscribe() 【取消订阅】方法的参数; * subscription.unsubscribe(); */ /** * result即是响应结果 */ stompClient.subscribe('/topic/game_chat', function (result) { console.info(result) showContent(JSON.parse(result.body)); }); }); }
连接上端点,端点在WebSocketConfig配置文件里面配置开放
回调等待,等待服务器指定的路由发送消息
3).输入内容后点击发送调用方法:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 发送消息:调用接口 */ function sendName() { /** * 1.连接成功后,客户端可使用 send() 方法向服务器发送信息: * 2.client.send(destination url[, headers[, body]]); * 1.destination url 为服务器 controller中【@MessageMapping】中匹配的URL,字符串,必须参数; * 2.headers 为发送信息的header,JavaScript 对象,可选参数; * 3.body 为发送信息的 body,字符串,可选参数; * 4.发送的消息可被【订阅】了的客户端接收展示 */ stompClient.send("/app/v1/chat", {}, JSON.stringify({'content': $("#content").val()})); }
向服务器指定接口(路由)发送消息,
(三).服务器接收到消息之后调用指定路由的api:return发送消息
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package xdclass_websocket.controller.v1; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import xdclass_websocket.model.InMessage; import xdclass_websocket.model.OutMessage; @Controller public class GameInfoController { @MessageMapping("/v1/chat")//发送消息设置的url @SendTo("/topic/game_chat")//订阅设置的url public OutMessage gameInfo(InMessage message){//接收消息 return new OutMessage(message.getContent());//发送消息 } }
sendTo给指定的订阅者
(四)服务器发送消息了,回调方法就生效了:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/** * 连接,回调 */ function connect() { /** * 连接上【端点】,在WebSocketConfig配置得一个端点 * 连接了的就调用展示公告的方法 */ var socket = new SockJS('/endpoint-websocket'); /** * 用stom进行包装,规范协议 */ stompClient = Stomp.over(socket); /** * client.connect(headers, connectCallback, errorCallback); * {} 回调 失败回调 */ stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); /** * 【订阅】: * 1.STOMP 客户端要想接收来自服务器推送的消息,必须先订阅相应的URL,即发送一个【SUBSCRIBE 帧】,然后才能不断接收来自服务器的推送消息; * 2.订阅和接收消息通过 subscribe() 方法实现:var subscription = subscribe(destination url, callback[, headers]) * 1.destination url 为服务器【@SendTo】匹配的 URL,字符串; * 2.callback 为每次收到服务器推送的消息时的回调方法,该方法包含参数 message; * 3.headers 为附加的headers,JavaScript 对象。 * 4.该方法返回一个包含了id属性的 JavaScript 对象,可作为 unsubscribe() 【取消订阅】方法的参数; * subscription.unsubscribe(); */ /** * result即是响应结果 */ stompClient.subscribe('/topic/game_chat', function (result) { console.info(result) showContent(JSON.parse(result.body)); }); }); }
回调调用展示的方法,进行消息的展示