SpringBoot2.x集成WebSocket

WebSocket 不做过多得介绍,这里有篇比较全面得文章      Spring Boot系列十六 WebSocket简介和spring boot集成简单消息代理

我这里是精简版,只挑出核心代码记录。免得浪费大家时间

⒈项目导入依赖

1         <!-- 引入 websocket 依赖-->
2         <dependency>
3             <groupId>org.springframework.boot</groupId>
4             <artifactId>spring-boot-starter-websocket</artifactId>
5         </dependency>

⒉编写websocket配置

 1 package cn.coreqi.consumer.config;
 2 
 3 import org.springframework.context.annotation.Configuration;
 4 import org.springframework.messaging.simp.config.MessageBrokerRegistry;
 5 import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
 6 import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
 7 import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
 8 
 9 /**
10  * 配置消息代理,默认情况下使用内置的消息代理。
11  * @EnableWebSocketMessageBroker 此注解表示使用STOMP协议来传输基于消息代理的消息,此时可以在@Controller类中使用@MessageMapping
12  */
13 @Configuration
14 @EnableWebSocketMessageBroker
15 //SpringBoot2.x将extends AbstractWebSocketMessageBrokerConfigurer改为 implements WebSocketMessageBrokerConfigurer
16 public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
17     /**
18      * 注册 Stomp的端点 配置对外暴露访问的端点
19      * @param registry
20      */
21     @Override
22     public void registerStompEndpoints(StompEndpointRegistry registry) {
23         registry.addEndpoint("/websocket-simple")   //添加STOMP协议的端点。
24                 // 这个URL是供WebSocket客户端或SockJS客户端连接服务端访问的地址。
25                 .setAllowedOrigins("*") //添加允许跨域访问
26                 .withSockJS();  //指定端点使用SockJS协议
27     }
28 
29     /**
30      * 配置消息代理
31      * @param registry
32      */
33     @Override
34     public void configureMessageBroker(MessageBrokerRegistry registry) {
35         //启动简单Broker,客户端请求地址符合配置的前缀,消息才会发送到这个broker
36         //客户端订阅当前服务端时需要添加以下请求前缀,topic一般用于广播推送,queue用于点对点推送
37         registry.enableSimpleBroker("/userTest","/topicTest");
38         //如果不设置下面这一句,使用SimpMessagingTemplate.convertAndSendToUser向指定用户推送消息时
39         //订阅前缀只能为/user,例如前端订阅为/user/fanqi/info
40         registry.setUserDestinationPrefix("/userTest");
41         //客户端(html客户端、java客户端等)向服务端发送消息的请求前缀
42         registry.setApplicationDestinationPrefixes("/app");
43     }
44 
45 }

⒊编写控制器

 1 package cn.coreqi.consumer.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.messaging.handler.annotation.MessageMapping;
 5 import org.springframework.messaging.handler.annotation.SendTo;
 6 import org.springframework.messaging.simp.SimpMessagingTemplate;
 7 import org.springframework.scheduling.annotation.EnableScheduling;
 8 import org.springframework.scheduling.annotation.Scheduled;
 9 import org.springframework.stereotype.Controller;
10 import org.springframework.web.bind.annotation.RequestMapping;
11 
12 import java.text.DateFormat;
13 import java.text.SimpleDateFormat;
14 import java.util.Date;
15 
16 @Controller
17 @EnableScheduling   //定时任务支持
18 public class WebSocketController {
19 
20     @Autowired
21     private SimpMessagingTemplate messagingTemplate;
22 
23 
24     @RequestMapping("/")
25     public String index() {
26         return "index";
27     }
28 
29     /**
30      * 这里用于客户端推送消息到服务端,推送地址为:setApplicationDestinationPrefixes("/app")设置得前缀加上@MessageMapping注解得地址
31      * 此处为/app/send
32      * 当前方法处理后将结果转发给@SendTo注解得地址,如果没有指定,则采用默认
33      * @MessageMapping 指定要接收消息的地址,类似@RequestMapping。除了注解到方法上,也可以注解到类上
34      * @SendTo 默认消息将被发送到与传入消息相同的目的地,但是目的地前面附加前缀(默认情况下为"/topic")
35      * @param message 客户端推送过来得消息,一般生产环境会封装
36      * @return
37      * @throws Exception
38      */
39     @MessageMapping("/send")
40     @SendTo("/topicTest/web-to-server-to-web")
41     public String greeting(String message) throws Exception {
42         // 模拟延时,以便测试客户端是否在异步工作
43         Thread.sleep(1000);
44         return "Hello, " + message + "!";
45     }
46 
47     /**
48      * 最基本的服务器端主动推送消息给客户端
49      * @return
50      * @throws Exception
51      */
52     @Scheduled(initialDelay = 7000,fixedRate = 2000)
53     public String serverTime() throws Exception {
54         // 发现消息
55         DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
56         messagingTemplate.convertAndSend("/topicTest/servertime", df.format(new Date()));
57         return "servertime";
58     }
59 
60     /**
61      * 服务端推送消息到指定用户得客户端
62      * 例如以下将会推送到
63      * 因为设置了setUserDestinationPrefix("/userTest"),因此推送到/userTest/fanqi/info
64      * 如果没有设置setUserDestinationPrefix(),则默认前端为user,将会推送到/user/fanqi/info
65      * 客户端订阅/userTest/fanqi/info将会收到服务端推送得消息
66      * @return
67      * @throws Exception
68      */
69     @Scheduled(initialDelay = 7000,fixedRate = 2000)
70     public String serverTimeToUser() throws Exception {
71         DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
72         messagingTemplate.convertAndSendToUser("fanqi","/info", df.format(new Date()));
73         return "serverTimeToUser";
74     }
75 }

⒋前端websocket客户端代码

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <title>玩转spring boot——websocket</title>
  5     <script src="https://cdn.bootcss.com/angular.js/1.5.6/angular.min.js"></script>
  6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
  7     <script src="https://cdn.bootcss.com/sockjs-client/1.3.0/sockjs.js"></script>
  8     <script src="https://cdn.bootcss.com/stomp.js/2.3.3/stomp.js"></script>
  9     <script type="text/javascript">
 10         var stompClient = null;
 11 
 12         var app = angular.module('app', []);
 13         app.controller('MainController', function($rootScope, $scope, $http) {
 14 
 15             $scope.data = {
 16                 connected : false,
 17                 sendMessage : '',
 18                 receivMessages : []
 19             };
 20 
 21             //连接
 22             $scope.connect = function() {
 23                 var socket = new SockJS('/websocket-simple');
 24                 stompClient = Stomp.over(socket);
 25                 stompClient.connect({}, function(frame) {
 26                     // 订阅后端主动推消息到前端的topic
 27                     stompClient.subscribe('/topicTest/servertime', function(r) {
 28                         $scope.data.time = '当前服务器时间:' + r.body;
 29                         $scope.data.connected = true;
 30                         $scope.$apply();
 31                     });
 32                     // 阅后端主动推消息到前端的topic,只有指定的用户(hzb)收到的的消息
 33                     stompClient.subscribe('/userTest/fanqi/info', function(r) {
 34                         $scope.data.hzbtime = '当前服务器时间:' + r.body;
 35                         $scope.data.connected = true;
 36                         $scope.$apply();
 37                     });
 38                     // 订阅前端发到后台,后台又将消息返回前台的topic
 39                     stompClient.subscribe('/topicTest/web-to-server-to-web', function(msg) {
 40                         $scope.data.receivMessages.push(msg.body);
 41                         $scope.data.connected = true;
 42                         $scope.$apply();
 43                     });
 44 
 45 
 46                     $scope.data.connected = true;
 47                     $scope.$apply();
 48                 });
 49             };
 50 
 51             $scope.disconnect = function() {
 52                 if (stompClient != null) {
 53                     stompClient.disconnect();
 54                 }
 55                 $scope.data.connected = false;
 56             }
 57 
 58             $scope.send = function() {
 59                 stompClient.send("/app/send", {}, JSON.stringify({
 60                     'message' : $scope.data.sendMessage
 61                 }));
 62             }
 63         });
 64     </script>
 65 </head>
 66 <body ng-app="app" ng-controller="MainController">
 67 
 68 <h2>websocket示例</h2>
 69 <label>WebSocket连接状态:</label>
 70 <button type="button" ng-disabled="data.connected" ng-click="connect()">连接</button>
 71 <button type="button" ng-click="disconnect()" ng-disabled="!data.connected">断开</button>
 72 <br/>
 73 <br/>
 74 <div ng-show="data.connected">
 75     <h4>以下是websocket的服务端主动推送消息到页面的例子</h4>
 76     <label>{{data.time}}</label> <br/> <br/>
 77 </div>
 78 <div ng-show="data.connected">
 79     <h4>以下是websocket的服务端主动推送消息到页面的例子,只有hzb这个用户收到</h4>
 80     <label>{{data.hzbtime}}</label> <br/> <br/>
 81 </div>
 82 <div ng-show="data.connected">
 83     <h4>以下是websocket的客户端发消息到服务端,服务端再将该消息返回到客户端(页面)的例子</h4>
 84     <input type="text" ng-model="data.sendMessage" placeholder="请输入内容..." />
 85     <button ng-click="send()" type="button">发送</button>
 86     <br/>
 87     <table>
 88         <thead>
 89         <tr>
 90             <th>消息内容:</th>
 91         </tr>
 92         </thead>
 93         <tbody>
 94         <tr ng-repeat="messageContent in data.receivMessages">
 95             <td>{{messageContent}}</td>
 96         </tr>
 97         </tbody>
 98     </table>
 99 </div>
100 </body>
101 </html>

 

posted @ 2019-07-31 14:59  SpringCore  阅读(3807)  评论(2编辑  收藏  举报