• jQuery火箭图标返回顶部代码


    我们首先要知道WebSocket的应用场景:

           ①在线股票网站

           ②即时聊天

           ③多人在线游戏

           ④应用集群通信

           ⑤系统性能及时监控

           ......

    下面让我们开始从项目中学习WebSocket:

    (一)首先创建一个Spring Boot项目,如下图,博主用的是IDEA:

              

              后续过程不太难,如果还是不太会的话,请看https://www.cnblogs.com/Trojan00/p/11317839.html

    (二)添加依赖:

              

    (三)配置WebSocket(WebScoketMessageBroker.java):

     1 package com.example.demo;
     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 @Configuration
    10 @EnableWebSocketMessageBroker
    11 public class WebScoketMessageBroker implements WebSocketMessageBrokerConfigurer {
    12     @Override
    13     public void configureMessageBroker(MessageBrokerRegistry config){
    14         config.enableSimpleBroker("/topic");
    15         config.setApplicationDestinationPrefixes("/app");
    16     }
    17     @Override
    18     public void registerStompEndpoints(StompEndpointRegistry registry){
    19         registry.addEndpoint("/chat").withSockJS();
    20     }
    21 }

                讲解时间到:

                               ①自定义类WebSocketConfig继承自WebSocketMessageBrokerConfigurer进

                                  行WebSocket配置,然后通过@EnableWebSocketMessageBgroker注解开启

                                  WebSocket消息代理;

                               ②config.enableSimpleBroker("/topic")表示设置消息代理的前缀,即如果消息

                                  前缀是"/topic",就会将消息转发给消息代理(Broker),再由消息代理将消息广

                                  播给当前连接的客户端。

                              ③config.setApplicationDestinationPrefixes("/app")表示配置一个或多个前缀,

                                  通过这些前缀过滤出需要备注接方法处理的消息。例如,前缀为“/app”的d-

                                  estination可以通过@MessageMapping注解的方法处理,而其他destination

                                  (例如:"/topic" "/queue")将被直接交给broker处理。

                              ④registry.adEndpoing("/chat").withSockJS()则表示定义一个前缀为"/chat"的

                                  EndPoint,并开启sockjs支持,sockjs可以解决浏览器对WebSocket的兼容性

                                  问题,客户户端将通过这里配置的URL来建立WebSocket连接。

    (四)定义Controller(GreetingController.java):

     1 package org.sang.wschat.controller;
     2 
     3 import org.sang.wschat.model.Chat;
     4 import org.sang.wschat.model.Message;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.messaging.handler.annotation.MessageMapping;
     7 import org.springframework.messaging.handler.annotation.SendTo;
     8 import org.springframework.messaging.simp.SimpMessagingTemplate;
     9 import org.springframework.scheduling.annotation.Scheduled;
    10 import org.springframework.stereotype.Controller;
    11 
    12 import java.security.Principal;
    13 
    14 @Controller
    15 public class GreetingController {
    16     @Autowired
    17     SimpMessagingTemplate messagingTemplate;
    18 
    19     @MessageMapping("/hello")
    20     @SendTo("/topic/greetings")
    21     public Message greeting(Message message) throws Exception {
    22         return message;
    23     }
    24 //    @MessageMapping("/chat")
    25 //    public void chat(Principal principal, Chat chat) {
    26 //        String from = principal.getName();
    27 //        chat.setFrom(from);
    28 //        messagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
    29 //    }
    30 }

                讲解时间到:

                                     在这一段代码中我们看到@MessageMapping("/hello")注解的方法将用来接

                                     收"/app/hello"(上一段代码讲解的第三步)路径发送来的消息,在注解方法

                                     对消息处理后,再将消息转发到@SendTo定义的路径上,儿@SendTo路径是

                                     一个前缀为"/topic"的路径,所以该消息将被交给消息代理的broker, 之后再

                                    由broker进行广播(上一段代码讲解的第三步)。

             快捷聊天界面构建(chat.html):

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>群聊</title>
     6     <script src="/webjars/jquery/jquery.min.js"></script>          //外部JS,添加依赖是有添加
     7     <script src="/webjars/sockjs-client/sockjs.min.js"></script>   //外部JS
     8     <script src="/webjars/stomp-websocket/stomp.min.js"></script>  //外部JS
     9     <script src="/app.js"></script>
    10 </head>
    11 <body>
    12 <div>
    13     <label for="name">请输入用户名:</label>
    14     <input type="text" id="name" placeholder="用户名">
    15 </div>
    16 <div>
    17     <button id="connect" type="button">连接</button>
    18     <button id="disconnect" type="button" disabled="disabled">断开连接</button>
    19 </div>
    20 <div id="chat" style="display: none;">
    21     <div>
    22         <label for="name">请输入聊天内容:</label>
    23         <input type="text" id="content" placeholder="聊天内容">
    24     </div>
    25     <button id="send" type="button">发送</button>
    26     <div id="greetings">
    27         <div id="conversation" style="display: none">群聊进行中...</div>
    28     </div>
    29 </div>
    30 </body>
    31 </html>

             app.js:

     1 var stompClient = null;
     2 function setConnected(connected) {
     3     $("#connect").prop("disabled", connected);
     4     $("#disconnect").prop("disabled", !connected);
     5     if (connected) {
     6         $("#conversation").show();
     7         $("#chat").show();
     8     }
     9     else {
    10         $("#conversation").hide();
    11         $("#chat").hide();
    12     }
    13     $("#greetings").html("");
    14 }
    15 function connect() {
    16     if (!$("#name").val()) {
    17         return;
    18     }
    19     // registry.addEndpoint("/chat").withSockJS()中的那个"/chat"
    20     var socket = new SockJS('/chat');  
    21     stompClient = Stomp.over(socket);
    22     stompClient.connect({}, function (frame) {
    23         setConnected(true);
    24         // 第一个参数就是目的地地址
    25         stompClient.subscribe('/topic/greetings', function (greeting) {
    26             showGreeting(JSON.parse(greeting.body));
    27         });
    28     });
    29 }
    30 function disconnect() {
    31     if (stompClient !== null) {
    32         stompClient.disconnect();
    33     }
    34     setConnected(false);
    35 }
    36 function sendName() {
    37     // 发送,第一个参数就是GreetingController中的发送源地址
    38     stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val(),'content':$("#content").val()}));
    39 }
    40 function showGreeting(message) {
    41     $("#greetings").append("<div>" + message.name+":"+message.content + "</div>");
    42 }
    43 
    44 $(function () {
    45     //分别是点击连接、断开连接、发送三个事件,以及对应出发的函数
    46     $( "#connect" ).click(function() { connect(); });
    47     $( "#disconnect" ).click(function() { disconnect(); });
    48     $( "#send" ).click(function() { sendName(); });
    49 });

                运行(打开两个页面,进入chat.html,并输入两个用户名,然后点击连接,就可以输入内容了

             ,输入好就可点击发送了):

             

    (五) 接下来让我们看一下点对点的传送吧!点对点,所以有了用户,因此用到了spring security,故

               先要添加Spring Security的依赖;

    (六)配置Spring SecurityWebSecurityConfig

     1 package org.sang.wschat.config;
     2 
     3 import org.springframework.context.annotation.Bean;
     4 import org.springframework.context.annotation.Configuration;
     5 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     6 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     8 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     9 import org.springframework.security.crypto.password.PasswordEncoder;
    10 
    11 @Configuration
    12 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    13     @Bean
    14     PasswordEncoder passwordEncoder() {
    15         return new BCryptPasswordEncoder();
    16     }
    17     @Override
    18     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    19         auth.inMemoryAuthentication()
    20         .withUser("admin")
    21         .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") //即123
    22         .roles("admin")
    23         .and()
    24         .withUser("sang")
    25         .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq") //即123
    26         .roles("user");
    27     }
    28     @Override
    29     protected void configure(HttpSecurity http) throws Exception {
    30         http.authorizeRequests()
    31                 .anyRequest().authenticated()
    32                 .and()
    33                 .formLogin().permitAll();
    34     }
    35 }

    (七)改造WebSocket(WebSocketConfig.java):

     1 package org.sang.wschat.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 @Configuration
    10 @EnableWebSocketMessageBroker
    11 public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    12     @Override
    13     public void configureMessageBroker(MessageBrokerRegistry config) {
    14         config.enableSimpleBroker("/topic","/queue");  //就这里多加了个"/queue"
    15         config.setApplicationDestinationPrefixes("/app");
    16     }
    17     @Override
    18     public void registerStompEndpoints(StompEndpointRegistry registry) {
    19         registry.addEndpoint("/chat").withSockJS();
    20     }
    21 }

    (八)配置Controller:

     1 package org.sang.wschat.controller;
     2 
     3 import org.sang.wschat.model.Chat;
     4 import org.sang.wschat.model.Message;
     5 import org.springframework.beans.factory.annotation.Autowired;
     6 import org.springframework.messaging.handler.annotation.MessageMapping;
     7 import org.springframework.messaging.handler.annotation.SendTo;
     8 import org.springframework.messaging.simp.SimpMessagingTemplate;
     9 import org.springframework.scheduling.annotation.Scheduled;
    10 import org.springframework.stereotype.Controller;
    11 
    12 import java.security.Principal;
    13 
    14 @Controller
    15 public class GreetingController {
    16     @Autowired
    17     SimpMessagingTemplate messagingTemplate;
    18 
    19     @MessageMapping("/hello")
    20     @SendTo("/topic/greetings")
    21     public Message greeting(Message message) throws Exception {
    22         return message;
    23     }
    24     @MessageMapping("/chat")
    25     public void chat(Principal principal, Chat chat) {
    26         String from = principal.getName();
    27         chat.setFrom(from);
    28         messagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);  
    29     }
    30 }

    (九)创建聊天界面(类似于chat.html,此处是onlinechat.html):

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>单聊</title>
     6     <script src="/webjars/jquery/jquery.min.js"></script>
     7     <script src="/webjars/sockjs-client/sockjs.min.js"></script>
     8     <script src="/webjars/stomp-websocket/stomp.min.js"></script>
     9     <script src="/chat.js"></script>
    10 </head>
    11 <body>
    12 <div id="chat">
    13     <div id="chatsContent">
    14     </div>
    15     <div>
    16         请输入聊天内容:
    17         <input type="text" id="content" placeholder="聊天内容">
    18         目标用户:
    19         <input type="text" id="to" placeholder="目标用户">
    20         <button id="send" type="button">发送</button>
    21     </div>
    22 </div>
    23 </body>
    24 </html>

    (十)该轮到chat.js了,类似于点对点之前的那个项目的app.js:

     1 var stompClient = null;
     2 function connect() {
     3     var socket = new SockJS('/chat');
     4     stompClient = Stomp.over(socket);
     5     stompClient.connect({}, function (frame) {
     6         stompClient.subscribe('/user/queue/chat', function (chat) {
     7             showGreeting(JSON.parse(chat.body));
     8         });
     9     });
    10 }
    11 function sendMsg() {
    12     stompClient.send("/app/chat", {}, JSON.stringify({'content':$("#content").val(), 'to':$("#to").val()}));
    13 }
    14 function showGreeting(message) {
    15     $("#chatsContent").append("<div>" + message.from+":"+message.content + "</div>");
    16 }
    17 $(function () {
    18     connect();
    19     $( "#send" ).click(function() { sendMsg(); });
    20 });

                注:点对点这里要注意,第6行,路径是"/user/queue/chat",因为这个destinationPrefix默认值是

              "/user",也就是说消息的最终发送路径是"/user/用户名/queue.chat"

              结果如下:

              

     

    ADD:其实这个里面还有两个Mode,一个是Message的,另一个是Chat的,读者可以下载完整源代码自

               行研究,这个项目的完整源代码地址:https://github.com/Stray-Kite/WsChat

  • 相关阅读:
    hdu 1240:Asteroids!(三维BFS搜索)
    hdu 2199:Can you solve this equation?(二分搜索)
    hdu 1195:Open the Lock(暴力BFS广搜)
    【ACM
    hrbustoj 1161:Leyni(树状数组练习)
    时间作为横轴的图表(morris.js)超越昨天的自己系列(8)
    Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
    Sharded实现学习-我们到底能走多远系列(32)
    初始化IoC容器(Spring源码阅读)-我们到底能走多远系列(31)
    一致性哈希算法 应用场景(转)
  • 原文地址:https://www.cnblogs.com/Trojan00/p/11317792.html
Copyright © 2020-2023  润新知