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

Spring Boot是一个快速开发框架,可以帮助我们快速构建Web应用程序。在本攻略中,我们将使用Spring Boot和WebSocket创建一个私有即时通信系统。以下是完整攻略:

  1. 创建一个Maven项目,并在pom.xml文件添加以下依赖项:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 创建一个WebSocket配置类,并使用@Configuration注解将其标记为Spring配置类。在配置类中,创建一个WebSocketHandler实例,并使用@Bean注解将其注入到Spring容器中。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("*");
    }

    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }
}

在上面的示例中,我们使用@EnableWebSocket注解启用WebSocket支持。我们还使用registerWebSocketHandlers()方法注册WebSocket处理程序,并使用setAllowedOrigins()方法设置允许的来源。我们还使用@Bean注解将MyHandler实例注入到Spring容器中。

  1. 创建一个WebSocket处理程序类,并实现WebSocketHandler接口。在处理程序类中,实现afterConnectionEstablished()方法和handleTextMessage()方法。
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class MyHandler extends TextWebSocketHandler {

    private Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        String[] parts = payload.split(":");
        String recipient = parts[0];
        String content = parts[1];
        WebSocketSession recipientSession = sessions.get(recipient);
        if (recipientSession != null && recipientSession.isOpen()) {
            recipientSession.sendMessage(new TextMessage(content));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
    }
}

在上面的示例中,我们使用ConcurrentHashMap来存储WebSocket会话。我们实现了afterConnectionEstablished()方法来添加新的会话。我们还实现了handleTextMessage()方法来处理文本消息。在该方法中,我们解析消息的接收者和内容,并将消息发送给接收者。最后,我们实现了afterConnectionClosed()方法来删除会话。

  1. 创建一个控制器类,并使用@RestController注解将其标记为控制器。在控制器类中,创建一个处理HTTP GET请求的方法,并使用@RequestMapping注解将其映射到URL路径。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @RequestMapping("/")
    public String index() {
        return "Hello, World!";
    }
}
  1. src/main/resources/static目录下创建一个index.html文件,并添加以下内容:
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Example</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        var socket = new WebSocket("ws://" + window.location.host + "/myHandler");

        socket.onmessage = function(event) {
            var message = event.data;
            $("#messages").append("<p>" + message + "</p>");
        };

        function sendMessage() {
            var recipient = $("#recipient").val();
            var content = $("#content").val();
            var message = recipient + ":" + content;
            socket.send(message);
        }
    </script>
</head>
<body>
    <h1>WebSocket Example</h1>
    <div>
        <label for="recipient">Recipient:</label>
        <input type="text" id="recipient">
    </div>
    <div>
        <label for="content">Content:</label>
        <input type="text" id="content">
    </div>
    <button onclick="sendMessage()">Send</button>
    <div id="messages"></div>
</body>
</html>

在上面的示例中,我们使用JavaScript创建一个WebSocket连接,并使用onmessage事件处理程序来处理接收到的消息。我们还创建了一个sendMessage()函数来发送消息。在HTML中,我们使用<input>元素来获取接收者和内容,并使用<button>元素来触发sendMessage()函数。我们还使用<div>元素来显示接收到的消息。

  1. 运行应用程序。在浏览器中访问http://localhost:8080/,将看到一个Web页面。在页面中,输入接收者和内容,并单击“Send”按钮。在页面下方,将显示接收到的消息。

以上是使用Spring Boot和WebSocket创建私有即时通信系统的完整攻略。下面是两个示例,演示如何使用Spring Boot和WebSocket创建更复杂的Web应用程序:

示例1:使用Spring Security保护WebSocket连接

在这个示例中,我们将使用Spring Security来保护WebSocket连接。我们将创建一个控制器类,并使用Spring Security来限制访问WebSocket连接。

  1. 在pom.xml文件中添加以下依赖项:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 创建一个Spring Security配置类,并使用@Configuration注解将其标记为Spring配置类。在配置类中,创建一个UserDetailsService实例,并使用@Bean注解将其注入到Spring容器中。我们还使用configure()方法配置Spring Security。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
        return manager;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/myHandler").hasRole("USER")
            .and()
            .formLogin();
    }
}

在上面的示例中,我们使用@EnableWebSecurity注解启用Spring Security支持。我们使用userDetailsService()方法创建一个InMemoryUserDetailsManager实例,并使用withDefaultPasswordEncoder()方法设置密码编码器。我们还使用configure()方法配置Spring Security,限制访问WebSocket连接。

  1. 创建一个控制器类,并使用@RestController注解将其标记为控制器。在控制器类中,创建一个处理HTTP GET请求的方法,并使用@RequestMapping注解将其映射到URL路径。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @RequestMapping("/")
    public String index() {
        return "Hello, World!";
    }
}
  1. 创建一个WebSocket处理程序类,并实现WebSocketHandler接口。在处理程序类中,实现afterConnectionEstablished()方法和handleTextMessage()方法。
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class MyHandler extends TextWebSocketHandler {

    private Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        sessions.put(username, session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        String payload = message.getPayload();
        String[] parts = payload.split(":");
        String recipient = parts[0];
        String content = parts[1];
        WebSocketSession recipientSession = sessions.get(recipient);
        if (recipientSession != null && recipientSession.isOpen()) {
            recipientSession.sendMessage(new TextMessage(username + ": " + content));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        sessions.remove(username);
    }
}

在上面的示例中,我们使用SecurityContextHolder来获取当前用户的身份验证信息。我们使用身份验证信息的用户名来存储WebSocket会话。在handleTextMessage()方法中,我们将发送者的用户名添加到消息中。

  1. src/main/resources/static目录下创建一个index.html文件,并添加以下内容:
<!DOCTYPE html>
<html>
<head>
    <title>WebSocket Example</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        var socket = new WebSocket("ws://" + window.location.host + "/myHandler");

        socket.onmessage = function(event) {
            var message = event.data;
            $("#messages").append("<p>" + message + "</p>");
        };

        function sendMessage() {
            var recipient = $("#recipient").val();
            var content = $("#content").val();
            var message = recipient + ":" + content;
            socket.send(message);
        }
    </script>
</head>
<body>
    <h1>WebSocket Example</h1>
    <div>
        <label for="recipient">Recipient:</label>
        <input type="text" id="recipient">
    </div>
    <div>
        <label for="content">Content:</label>
        <input type="text" id="content">
    </div>
    <button onclick="sendMessage()">Send</button>
    <div id="messages"></div>
</body>
</html>

在上面的示例中,我们使用JavaScript创建一个WebSocket连接,并使用onmessage事件处理程序来处理接收到的消息。我们还创建了一个sendMessage()函数来发送消息。在HTML中,我们使用<input>元素来获取接收者和内容,并使用<button>元素来触发sendMessage()函数。我们还使用<div>元素来显示接收到的消息。

  1. 运行应用程序。在浏览器中访问http://localhost:8080/,将看到一个Web页面。在页面中,输入接收者和内容,并单击“Send”按钮。在页面下方,将显示接收到的消息。

示例2:使用SockJS和STOMP协议

在这个示例中,我们将使用SockJS和STOMP协议来创建一个更高级的WebSocket应用程序。我们将创建一个控制器类,并使用SockJS和STOMP协议来实现WebSocket连接。

  1. 在pom.xml文件中添加以下依赖项:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>sockjs-client</artifactId>
    <version>1.3.0</version>
</dependency>

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>stomp-websocket</artifactId>
    <version>2.3.3</version>
</dependency>
  1. 创建一个控制器类,并使用@RestController注解将其标记为控制器。在控制器类中,创建一个处理HTTP GET请求的方法,并使用@RequestMapping注解将其映射到URL路径。
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @RequestMapping("/")
    public String index() {
        return "Hello, World!";
    }
}
  1. 创建一个WebSocket处理程序类,并实现WebSocketHandler接口。在处理程序类中,实现afterConnectionEstablished()方法和handleTextMessage()方法。
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class MyHandler extends TextWebSocketHandler {

    private Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    private SimpMessagingTemplate messagingTemplate;

    public MyHandler(SimpMessagingTemplate messagingTemplate) {
        this.messagingTemplate = messagingTemplate;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.put(session.getId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        String[] parts = payload.split(":");
        String recipient = parts[0];
        String content = parts[1];
        messagingTemplate.convertAndSendToUser(recipient, "/queue/messages", content);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
    }
}

在上面的示例中,我们使用ConcurrentHashMap来存储WebSocket会话。我们实现了afterConnectionEstablished()方法来添加新的会话。我们还实现了handleTextMessage()方法来处理文本消息。在该方法中,我们解析消息的接收者和内容,并使用SimpMessagingTemplate来发送消息。最后,我们实现了afterConnectionClosed()方法来删除会话。

  1. 创建一个WebSocket配置类,并使用@Configuration注解将其标记为Spring配置类。在配置类中,创建一个WebSocketHandler实例,并使用@Bean注解将其注入到Spring容器中。我们还使用configureMessageBroker()方法配置消息代理。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("*");
    }

    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler(messagingTemplate());
    }

    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        container.setMaxTextMessageBufferSize(8192);
        container.setMaxBinaryMessageBufferSize(8192);
        return container;
    }

    @Bean
    public SimpMessagingTemplate messagingTemplate() {
        return new SimpMessagingTemplate(createWebSocketClient());
    }

    @Bean
    public WebSocketClient createWebSocketClient() {
        return new StandardWebSocketClient();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/queue");
        registry.setApplicationDestinationPrefixes("/app");
    }
}

在上面的示例中,我们使用@EnableWebSocket注解启用WebSocket支持。我们使用registerWebSocketHandlers()方法注册WebSocket处理程序,并使用setAllowedOrigins()方法设置允许的来源。我们还使用@Bean注解将MyHandler实例注入到Spring容器中。我们使用createWebSocketContainer()方法创建一个ServletServerContainerFactoryBean实例,并设置最大消息缓冲区大小。我们还使用messagingTemplate()方法创建一个SimpMessagingTemplate实例,并使用createWebSocketClient()方法创建一个WebSocketClient实例。最后,我们使用configureMessageBroker()方法配置消息代理。

  1. src/main/resources/static目录下创建一个index.html文件,并添加以下内容:

```html




WebSocket Example



  • java获取文件大小的几种方法

    当我们需要获取文件的大小时,有多种方法可以实现。下面将介绍java中获取文件大小的几种方法。 使用File类的length方法获取文件大小 File类是Java中常用的文件操作类,它提供了获取文件大小的方法length。该方法返回的是文件的字节数。 import java.io.File; public class FileSizeTest { public…

    Java 2023年5月20日
    00
  • 一天吃透Redis面试八股文

    Redis连环40问,绝对够全! Redis是什么? Redis(Remote Dictionary Server)是一个使用 C 语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis 的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis的操作是原子性的。…

    Java 2023年5月1日
    00
  • java编程之递归算法总结

    Java编程之递归算法总结 什么是递归算法 递归算法是指一个函数在运行过程中调用它自己的情况。递归函数通常包含一个终止条件,当达到这个条件时,函数将不再调用自身,防止形成无限循环。递归算法在计算机科学中有着广泛的应用,例如树形数据结构的遍历、排序、查找等。 递归算法的基本原则 递归算法的基本原则是分为两个部分: 基本情况(Base Case):表示递归终止的…

    Java 2023年5月19日
    00
  • Java Class.forName()用法和newInstance()方法原理解析

    Java中的Class对象提供了一些强大的机制来处理编译时期未知的类,比如在运行时动态加载并实例化一个类。其中Class.forName()和newInstance()方法是两个非常重要的方法,本文将详细讲解它们的用法和原理。 Java Class.forName()方法 Class.forName()是Java反射机制中的核心方法之一,它可以根据类名动态加…

    Java 2023年5月26日
    00
  • Java Apache Commons报错“SAXNotRecognizedException”的原因与解决方法

    “SAXNotRecognizedException”是Java的Apache Commons类库中的一个异常,通常由以下原因之一引起: 无效的SAX属性:如果SAX属性无效,则可能会出现此错误。在这种情况下,需要检查SAX属性以解决此问题。 无效的SAX特性:如果SAX特性无效,则可能会出现此错误。在这种情况下,需要检查SAX特性以解决此问题。 以下是两个…

    Java 2023年5月5日
    00
  • 合作推广
    合作推广
    分享本页
    返回顶部