赞
踩
WebSocket是一种在单个TCP连接上进行全双工通信的协议。这种协议在2011年被IETF定为标准RFC 6455,并由RFC7936补充规范,同时WebSocket API也被W3C定为标准。它使得客户端和服务器之间的数据交换变得更加简单,特别是允许服务端主动向客户端推送数据。
WebSocket技术具有一系列显著特点:
WebSocket的应用场景非常广泛,包括但不限于:
注意,WebSocket也存在一些潜在的问题,如兼容性问题(特别是在一些旧版本的浏览器上),服务器资源占用(由于需要维护大量的长连接),以及安全性问题(需要特殊的安全设置以防止恶意攻击和数据泄漏)。
首先,你需要在你的pom.xml
(如果你使用Maven)或build.gradle
(如果你使用Gradle)中添加Spring Boot WebSocket的依赖。
对于Maven,添加以下依赖:
- <dependencies>
- <!-- Spring Boot Starter WebSocket -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-websocket</artifactId>
- </dependency>
- <!-- 如果你还需要HTTP功能 -->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!-- 其他依赖... -->
- </dependencies>
对于Gradle,添加以下依赖:
- dependencies {
- // Spring Boot Starter WebSocket
- implementation 'org.springframework.boot:spring-boot-starter-websocket'
- // 如果你还需要HTTP功能
- implementation 'org.springframework.boot:spring-boot-starter-web'
- // 其他依赖...
- }
接下来,你需要配置WebSocket端点。我们继承WebMvcConfigurationSupport。以下是一个简单的配置示例:
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- /**
- * 开启WebSocket支持 配置websocket并开启
- */
- @Configuration
- public class WebSocketConfig extends WebMvcConfigurationSupport {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
-
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- super.addResourceHandlers(registry);
- // 相对路径
- registry.addResourceHandler("image/**").addResourceLocations("classpath:/static/image/");
- // 绝对路径
- // registry.addResourceHandler("image/**").addResourceLocations("file:" + "image/");
- }
- }

上述代码的WebSocketConfig该类继承自WebMvcConfigurationSupport
,并试图同时配置WebSocket和静态资源处理。然而,这种设计是有问题的,原因如下:
继承WebMvcConfigurationSupport
: 继承WebMvcConfigurationSupport
会关闭Spring Boot的自动配置功能,这意味着您将失去很多Spring Boot为MVC提供的默认配置。通常,如果您只是想要添加或覆盖某些配置,而不是完全自定义整个MVC配置,那么不推荐继承WebMvcConfigurationSupport
。
WebSocket配置: 在这个配置类中,@Bean
注解创建一个ServerEndpointExporter
的bean,这通常用于配置JSR 356 (Java API for WebSocket) 的端点。但是,ServerEndpointExporter
并不是Spring Boot的WebSocket消息代理的一部分,而是用于JSR 356 WebSocket端点的导出。如果您打算使用Spring的WebSocket消息代理(即STOMP over WebSocket),那么您不需要ServerEndpointExporter
。
静态资源处理: 通过覆盖addResourceHandlers
方法来配置静态资源的位置。尽管这本身不是错误的,但如果您只是想要配置静态资源,那么您并不需要继承WebMvcConfigurationSupport
。您可以直接在另一个配置类中通过实现WebMvcConfigurer
接口来完成这个操作。
如果您打算使用Spring的WebSocket消息代理,那么您应该使用类似您之前的WebSocketConfig
配置类(不继承WebMvcConfigurationSupport
),并实现WebSocketMessageBrokerConfigurer
接口。静态资源处理则可以通过实现WebMvcConfigurer
接口来完成。
以下是一个改进后的配置示例:
WebMvcConfigurationSupport
)- import org.springframework.context.annotation.Configuration;
- import org.springframework.messaging.simp.config.MessageBrokerRegistry;
- import org.springframework.web.socket.config.annotation.*;
-
- // 使用@Configuration注解来标识这个类是一个配置类
- @Configuration
- // 使用@EnableWebSocketMessageBroker注解来启用WebSocket消息代理支持
- @EnableWebSocketMessageBroker
- public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
-
- @Override
- public void configureMessageBroker(MessageBrokerRegistry config) {
- // 配置消息代理的前缀,客户端订阅消息时需要使用这个前缀
- config.enableSimpleBroker("/topic");
- // 配置应用目标前缀,客户端发送消息到服务器时使用这个前缀
- config.setApplicationDestinationPrefixes("/app");
- }
-
- @Override
- public void registerStompEndpoints(StompEndpointRegistry registry) {
- // 注册一个STOMP协议的WebSocket端点,客户端将连接到这个端点
- // addEndpoint方法第一个参数是端点URL,第二个参数是使用的子协议,这里使用SockJS
- registry.addEndpoint("/websocket").withSockJS();
- }
-
- // (可选)配置跨域策略
- @Override
- public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
- registration.setMessageSizeLimit(8192); // 设置消息大小限制
- registration.setSendBufferSizeLimit(16384); // 设置发送缓冲区大小限制
- }
- }

WebMvcConfigurer
)- @Configuration
- public class WebMvcConfig implements WebMvcConfigurer {
-
- @Override
- public void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("image/**")
- .addResourceLocations("classpath:/static/image/");
- // 如果需要绝对路径,可以添加另一个资源处理器
- }
- }
WebSocketController.java
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.messaging.handler.annotation.*;
- import org.springframework.stereotype.Controller;
-
- // 使用@Controller注解来标识这个类是一个控制器
- @Controller
- public class WebSocketController {
-
- // 假设有一个服务来处理消息逻辑
- @Autowired
- private MessageService messageService;
-
- // 使用@MessageMapping注解定义客户端发送消息到服务器的路由
- @MessageMapping("/hello")
- // 使用@SendTo注解定义服务器向客户端发送消息的路由
- @SendTo("/topic/greetings")
- public String greeting(String message) {
- // 调用服务来处理消息
- String processedMessage = messageService.processMessage(message);
- // 返回处理后的消息给客户端
- return processedMessage;
- }
-
- // (可选)定义一个方法处理连接事件
- @EventHandler
- public void handleConnect(SessionConnectedEvent event) {
- // 处理客户端连接事件
- }
-
- // (可选)定义一个方法处理断开连接事件
- @EventHandler
- public void handleDisconnect(SessionDisconnectEvent event) {
- // 处理客户端断开连接事件
- }
- }

MessageService.java
- import org.springframework.stereotype.Service;
-
- // 使用@Service注解来标识这个类是一个服务类
- @Service
- public class MessageService {
-
- public String processMessage(String message) {
- // 这里可以添加消息处理的逻辑,比如格式化、验证等
- // 返回一个处理后的消息
- return "Hello, " + message + "!";
- }
- }
以上代码配置了一个简单的WebSocket服务器,包括WebSocket消息代理、端点配置以及消息处理器。
WebSocketConfig
类是WebSocket的配置类,通过实现 WebSocketMessageBrokerConfigurer
接口,定义了消息代理和端点的配置。WebSocketController
类是WebSocket的控制器,使用 @MessageMapping
注解来映射客户端发送的消息,并使用 @SendTo
注解来指定消息发送的路由。MessageService
类是一个简单的服务类,用来处理WebSocket接收到的消息。@ServerEndpoint
的注解实现websocket通信在Spring框架中,@ServerEndpoint
注解用于声明一个WebSocket端点,这个端点可以被客户端通过WebSocket协议进行连接。然而,@ServerEndpoint
注解本身并不与Spring容器集成,所以直接使用@Component
注解来将其声明为一个Spring管理的bean是不起作用的。
要解决这个问题,你需要使用ServerEndpointExporter
来手动注册@ServerEndpoint
注解的类,以便它们能够被Spring容器管理。ServerEndpointExporter
是一个Spring Boot组件,它会自动注册带有@ServerEndpoint
注解的类,使其可以作为WebSocket端点。
以下是如何使用@ServerEndpoint
和@Component
注解,并通过ServerEndpointExporter
来实现WebSocket长连接的步骤:
1.创建一个带有@ServerEndpoint
注解的类,用于处理WebSocket连接。
- import javax.websocket.OnClose;
- import javax.websocket.OnMessage;
- import javax.websocket.OnOpen;
- import javax.websocket.Session;
- import javax.websocket.server.ServerEndpoint;
- import org.springframework.stereotype.Component;
-
- @ServerEndpoint("/ws/{userId}/{device}")
- @Component
- public class MyWebSocketEndpoint {
-
- @OnOpen
- public void onOpen(Session session, @PathParam("userId") String userId, @PathParam("device") String device) {
- // 连接建立时的处理逻辑
- System.out.println("Client connected: " + session.getId() + " with userId=" + userId + " and device=" + device);
- }
-
- @OnMessage
- public void onMessage(String message, Session session) {
- // 收到消息时的处理逻辑
- System.out.println("Message received: " + message + " from session: " + session.getId());
- }
-
- @OnClose
- public void onClose(Session session) {
- // 连接关闭时的处理逻辑
- System.out.println("Client disconnected: " + session.getId());
- }
- }

请注意,上面的代码中使用了@PathParam
注解来提取URL模板参数userId
和device
。但是,@PathParam
并不是javax.websocket
包中的一部分,它是JAX-RS规范的一部分。在标准的WebSocket API中,你需要在@OnOpen
方法中手动解析路径参数。
2. 创建一个配置类来注册ServerEndpointExporter
。
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- @Configuration
- public class WebSocketConfig {
-
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
- }
在这个配置类中,我们创建了一个ServerEndpointExporter
的bean,Spring Boot会自动扫描并注册所有带有@ServerEndpoint
注解的类。
请注意,@PathParam
注解在标准的WebSocket API中并不适用。如果你需要处理URL模板参数,你可能需要手动解析它们,或者使用Spring的@RequestMapping
和HandlerAdapter
来创建一个自定义的WebSocket端点处理器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。