實現游戲公告功能
實現功能:游戲管理里發布游戲公告,其它游戲玩家頁面能夠馬上接受到游戲公告信息。
下面直接上代碼案例,這里主要展示關鍵代碼,底部有源碼。
一、案例
1、pom.xml文件
主要是添加springBoot和webSocket相關jar包,和一些輔助工具jar包(注意我采用的是springBoot2.1.0版本

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jincou.websocket</groupId> <artifactId>websocketstudy</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>websocketstudy</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.BUILD-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!--springboot和websocket整合包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!--輔助包--> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator</artifactId> <version>0.32-1</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>sockjs-client</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>stomp-websocket</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>
2、WebSocketConfig
這個是websocket配置中心,配置一些核心配置。
import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration //注解用於開啟使用STOMP協議來傳輸基於代理(MessageBroker)的消息,這時候控制器(controller)開始支持@MessageMapping,就像是使用@requestMapping一樣。 @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { /** * 注冊端點,發布或者訂閱消息的時候需要連接此端點 * setAllowedOrigins 非必須,*表示允許其他域進行連接 * withSockJS 表示開始sockejs支持 */ public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/endpoint-websocket").setAllowedOrigins("*").withSockJS(); } /** * 配置消息代理(中介) * enableSimpleBroker 服務端推送給客戶端的路徑前綴 * setApplicationDestinationPrefixes 客戶端發送數據給服務器端的一個前綴 */ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } }
3、GameInfoController
管理員發布公告消息對應的接口
/* *模擬游戲公告 */ @Controller public class GameInfoController { //@MessageMapping和@RequestMapping功能類似,用於設置URL映射地址,瀏覽器向服務器發起請求,需要通過該地址。 //如果服務器接受到了消息,就會對訂閱了@SendTo括號中的地址傳送消息。 @MessageMapping("/gonggao/chat") @SendTo("/topic/game_chat") public OutMessage gameInfo(InMessage message){ return new OutMessage(message.getContent()); } }
4、管理員頁面和用戶頁面
admin頁面和user頁面唯一的區別就是管理員多一個發送公告的權限,其它都一樣,user1和user2完全一樣。
(1)admin.html

<!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="/gonggao/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="/gonggao/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>
(2)user1.html

<!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="/gonggao/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="/gonggao/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> <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>
(3)user2.html

<!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="/gonggao/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="/gonggao/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> <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>
5.app.js
這個是客戶端連接websocket的核心,通過html的點擊事件來完成。
var stompClient = null; //這個方法僅僅是用來改變樣式,不是核心 function setConnected(connected) { $("#connect").prop("disabled", connected); $("#disconnect").prop("disabled", !connected); if (connected) { $("#conversation").show(); } else { $("#conversation").hide(); } $("#notice").html(""); } //1、建立連接(先連接服務端配置文件中的基站,建立連接,然后訂閱服務器目錄消息 function connect() { //1、連接SockJS的endpoint是“endpoint-websocket”,與后台代碼中注冊的endpoint要一樣。 var socket = new SockJS('/endpoint-websocket'); //2、用stom進行包裝,規范協議 stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { //3、建立通訊 setConnected(true); console.log('Connected: ' + frame); //4、通過stompClient.subscribe()訂閱服務器的目標是'/topic/game_chat'發送過來的地址,與@SendTo中的地址對應。 stompClient.subscribe('/topic/game_chat', function (result) { console.info(result) showContent(JSON.parse(result.body)); }); }); } //2、關閉連接 function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } //3、游戲管理員發送公告信息(這個也是游戲用戶所沒有功能,其它都一樣) function sendName() { //1、通過stompClient.send 向/app/gonggao/chat 目標 發送消息,這個是在控制器的@messageMapping 中定義的。(/app為前綴,配置里配置) stompClient.send("/app/gonggao/chat", {}, JSON.stringify({'content': $("#content").val()})); } //4、訂閱的消息顯示在客戶端指定位置 function showContent(body) { $("#notice").append("<tr><td>" + body.content + "</td> <td>"+new Date(body.time).toLocaleString()+"</td></tr>"); } $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $( "#connect" ).click(function() { connect(); }); $( "#disconnect" ).click(function() { disconnect(); }); $( "#send" ).click(function() { sendName(); }); });
6、查看運行結果
7、小總結
首先很明顯看的出,websocket最大的優點,就是可以服務端主動向客戶端發送消息,而此前http只能是客戶端向服務端發送請求。
gitHub源碼:https://github.com/yudiandemingzi/spring-boot-websocket-study
想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要么別想,要么多做。中校【19】