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

yizhihongxing

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



  • JS版微信6.0分享接口用法分析

    下面我将详细讲解“JS版微信6.0分享接口用法分析”的完整攻略。 一、JS版微信6.0分享接口简介 JS版微信6.0分享接口是微信公众号提供的一种方式,允许网站开发者在网页端调用微信分享功能,从而使用户直接将网页内容分享到微信朋友圈、好友或者分组内的好友。 二、JS版微信6.0分享接口使用步骤 1. 引入JS文件 在HTML文件中的head标签内,加入如下代…

    Java 2023年5月26日
    00
  • 基于JSP实现一个简单计算器的方法

    基于JSP实现一个简单计算器的方法 1. 准备工作 确定需要实现的计算器功能,例如加减乘除四则运算、开方、取余等功能。 创建基于Maven的Web项目,添加所需的依赖。 “`xml javax.servlet jstl 1.2 taglibs standard 1.1.2 “` 在项目的src/main/webapp目录下创建转发器(Dispatcher…

    Java 2023年6月15日
    00
  • SpringMVC @ControllerAdvice使用场景

    以下是关于“SpringMVC @ControllerAdvice使用场景”的完整攻略,其中包含两个示例。 SpringMVC @ControllerAdvice使用场景 @ControllerAdvice是SpringMVC中的一个注解,用于定义全局的异常处理器和全局的数据绑定器。本文将介绍@ControllerAdvice的使用场景,并提供两个示例。 全…

    Java 2023年5月16日
    00
  • Java 用反射设置对象的属性值实例详解

    接下来我会用标准的markdown格式文本进行讲解,包含标题、代码块等内容。 Java 用反射设置对象的属性值实例详解 在Java中,我们经常需要对对象进行操作,其中一项操作是设置对象的属性值。使用反射机制可以在运行时动态地获取类的信息、创建对象、调用方法和操作属性。 在Java中,可以通过反射机制设置对象的属性值。下面是详细教学: 第一步:获取类对象 首先…

    Java 2023年5月26日
    00
  • 基于java实现的ECC加密算法示例

    题目中提到了“基于java实现的ECC加密算法示例”,因此我们需要对这个话题展开讲解,下面是详细的攻略: 什么是ECC加密算法? ECC(Elliptic Curve Cryptography)椭圆曲线加密算法,是在椭圆曲线上实现的加密算法。通常情况下,比如RSA加密算法,密钥长度越长,加密的强度也越强。但是,ECC加密算法却有一个比较特别的地方,那就是在密…

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