• 天天玩微信,Spring Boot 开发私有即时通信系统了解一下


    1/ 概述

    利用Spring Boot作为基础框架,Spring Security作为安全框架,WebSocket作为通信框架,实现点对点聊天和群聊天。

    2/ 所需依赖

    Spring Boot 版本 1.5.3,使用MongoDB存储数据(非必须),Maven依赖如下:

    <properties>
        <java.version>1.8</java.version>
        <thymeleaf.version>3.0.0.RELEASE</thymeleaf.version>
        <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>
      </properties>
    
      <dependencies>
    
        <!-- WebSocket依赖,移除Tomcat容器 -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-websocket</artifactId>
          <exclusions>
            <exclusion>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
    
        <!-- 使用Undertow容器 -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
    
        <!--  Spring Security 框架 -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
    
        <!-- MongoDB数据库 -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    
        <!-- Thymeleaf 模版引擎 -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.16.16</version>
        </dependency>
    
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>fastjson</artifactId>
          <version>1.2.30</version>
        </dependency>
    
        <!-- 静态资源 -->
        <dependency>
          <groupId>org.webjars</groupId>
          <artifactId>webjars-locator</artifactId>
        </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>
    
      </dependencies>
    

    配置文件内容:

    server:
      port: 80
    
    # 若使用MongoDB则配置如下参数
    spring:
      data:
        mongodb:
          uri: mongodb://username:password@172.25.11.228:27017
          authentication-database: admin
          database: chat
    

    大致程序结构,仅供参考:

    程序结构

    3/ 创建程序启动类,启用WebSocket

    使用@EnableWebSocket注解

    @SpringBootApplication
    @EnableWebSocket
    public class Application {
    
     public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
     }
    
    }
    

    4/ 配置Spring Security

    此章节省略。(配置好Spring Security,用户能正常登录即可)
    可以参考:Spring Boot 全栈开发:用户安全

    5/ 配置Web Socket(结合第7节的JS看)

    @Configuration
    @EnableWebSocketMessageBroker
    @Log4j
    public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    
      // 此处可注入自己写的Service
    
      @Override
      public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        // 客户端与服务器端建立连接的点
        stompEndpointRegistry.addEndpoint("/any-socket").withSockJS();
      }
    
      @Override
      public void configureMessageBroker(MessageBrokerRegistry messageBrokerRegistry) {
        // 配置客户端发送信息的路径的前缀
        messageBrokerRegistry.setApplicationDestinationPrefixes("/app");
        messageBrokerRegistry.enableSimpleBroker("/topic");
      }
    
      @Override
      public void configureWebSocketTransport(final WebSocketTransportRegistration registration) {
        registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {
          @Override
          public WebSocketHandler decorate(final WebSocketHandler handler) {
            return new WebSocketHandlerDecorator(handler) {
              @Override
              public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
                // 客户端与服务器端建立连接后,此处记录谁上线了
                String username = session.getPrincipal().getName();
                log.info("online: " + username);
                super.afterConnectionEstablished(session);
              }
    
              @Override
              public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
                // 客户端与服务器端断开连接后,此处记录谁下线了
                String username = session.getPrincipal().getName();
                log.info("offline: " + username);
                super.afterConnectionClosed(session, closeStatus);
              }
            };
          }
        });
        super.configureWebSocketTransport(registration);
      }
    }
    

    6/ 点对点消息,群消息

    @Controller
    @Log4j
    public class ChatController {
    
      @Autowired
      private SimpMessagingTemplate template;
    
      // 注入其它Service
    
      // 群聊天
      @MessageMapping("/notice")
      public void notice(Principal principal, String message) {  
        // 参数说明 principal 当前登录的用户, message 客户端发送过来的内容
        // principal.getName() 可获得当前用户的username  
    
        // 发送消息给订阅 "/topic/notice" 且在线的用户
        template.convertAndSend("/topic/notice", message); 
      }
    
      // 点对点聊天
      @MessageMapping("/chat")
      public void chat(Principal principal, String message){
        // 参数说明 principal 当前登录的用户, message 客户端发送过来的内容(应该至少包含发送对象toUser和消息内容content)
        // principal.getName() 可获得当前用户的username
    
        // 发送消息给订阅 "/user/topic/chat" 且用户名为toUser的用户
        template.convertAndSendToUser(toUser, "/topic/chat", content);
      }
    
    }
    

    7/ 客户端与服务器端交互

    var stompClient = null;
    
        function connect() {
            var socket = new SockJS('/any-socket');
            stompClient = Stomp.over(socket);
            stompClient.connect({}, function (frame) {
                // 订阅 /topic/notice 实现群聊
                stompClient.subscribe('/topic/notice', function (message) {
                    showMessage(JSON.parse(message.body));
                });
                // 订阅 /user/topic/chat 实现点对点聊
                stompClient.subscribe('/user/topic/chat', function (message) {
                    showMessage(JSON.parse(message.body));
                });
            });
        }
    
        function showMessage(message) {
            // 处理消息在页面的显示
        }
    
        $(function () {
            // 建立websocket连接
            connect();
            // 发送消息按钮事件
            $("#send").click(function () {
                if (target == "TO_ALL"){
                    // 群发消息
                    // 匹配后端ChatController中的 @MessageMapping("/notice")
                    stompClient.send("/app/notice", {}, '消息内容');
                }else{
                    // 点对点消息,消息中必须包含对方的username
                    // 匹配后端ChatController中的 @MessageMapping("/chat")
                    var content = "{'content':'消息内容','receiver':'anoy'}";
                    stompClient.send("/app/chat", {}, content);
                }
            });
        });
    

    8/ 效果测试

    登录三个用户:Anoyi、Jock、超级管理员。
    群消息测试,超级管理员群发消息:

    超级管理员

    Anoyi

    Jock

    点对点消息测试,Anoyi给Jock发送消息,只有Jock收到消息,Anoyi和超级管理员收不到消息:

    Jock

    超级管理员

    Anoyi

    9/ 轻量级DEMO(完整可运行代码)

    Spring Boot 开发私有即时通信系统(WebSocket)(续)

    10/ 参考文献

    • spring-mongodb 官方文档
    • Spring Framework 官方文档
    • Spring Guide - stomp websocket

    © 著作权归作者所有,转载或内容合作请联系作者

    有任何问题,请留言告诉我们哈。

    img

    Spring Boot 定制 parent 快速构建应用

    Spring Boot 容器化部署 - Docker

    SpringBot中教你手把手配置 https

    Spring Boot 日志处理你还在用Logback?

    【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?

    Spring Boot 新一代监控你该这么玩

    Spring Boot 异常处理

    Spring Boot 配置 - 配置信息加密

    拒绝黑盒应用-Spring Boot 应用可视化监控

    并发Bug之源有三,请睁大眼睛看清它们

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    linux内核主要模块图
    进程的用户栈和内核栈
    Linux0.11内核几种地址(逻辑地址、线性地址、物理地址)的含义
    实模式与保护模式
    Linux多线程与同步
    java+selenium——鼠标左击
    java+selenium——键盘操作+复制粘贴(keys类)
    java+selenium——语法简介
    java+selenium——鼠标悬停从一个位置移动到另外一个位置
    java+selenium——简单截图+保存在java工程目录下=====简单截图+时间+保存在java工程目录下
  • 原文地址:https://www.cnblogs.com/springforall/p/11826798.html
Copyright © 2020-2023  润新知