diff --git a/src/main/java/com/youlai/system/config/WebSocketConfig.java b/src/main/java/com/youlai/system/config/WebSocketConfig.java new file mode 100644 index 00000000..89618e92 --- /dev/null +++ b/src/main/java/com/youlai/system/config/WebSocketConfig.java @@ -0,0 +1,32 @@ +package com.youlai.system.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.simp.config.MessageBrokerRegistry; +import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; +import org.springframework.web.socket.config.annotation.StompEndpointRegistry; +import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; + +/** + * WebSocket 配置类 + * + * @author haoxr + * @since 2.3.0 + */ +@Configuration +@ConditionalOnProperty(name = "system.config.websocket-enabled")// system.config.websocket-enabled = true 才会自动装配 +@EnableWebSocketMessageBroker // 注解告诉Spring框架要开启WebSocket消息代理的功能,并配置相关的端点和消息代理 +public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { + + + @Override + public void configureMessageBroker(MessageBrokerRegistry registry) { + registry.enableSimpleBroker("/topic", "/user"); + } + + @Override + public void registerStompEndpoints(StompEndpointRegistry registry) { + // 注册了一个 /ws 的端点,用于建立WebSocket连接。 + registry.addEndpoint("/ws").setAllowedOriginPatterns("*"); + } +} diff --git a/src/main/java/com/youlai/system/controller/WebsocketController.java b/src/main/java/com/youlai/system/controller/WebsocketController.java new file mode 100644 index 00000000..3f7462f6 --- /dev/null +++ b/src/main/java/com/youlai/system/controller/WebsocketController.java @@ -0,0 +1,61 @@ +package com.youlai.system.controller; + +import cn.hutool.json.JSONUtil; +import com.youlai.system.common.result.Result; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * WebSocket 测试控制器 + * + * @author haoxr + * @since 2.3.0 + */ +@RestController +@RequestMapping("/websocket") +@RequiredArgsConstructor +@Slf4j +public class WebsocketController { + + private final SimpMessagingTemplate messagingTemplate; + + /** + * 广播发送消息 + * + * @param message 消息内容 + */ + @PostMapping("/sendToAll") + // @SendTo("/topic/all") // 使用SimpMessagingTemplate发送消息给所有订阅了"/topic/all"目标的客户端 + public Result sendToAll(String message) { + log.info("【广播消息请求接收】消息:{}", message); + // 处理接收到的消息逻辑 + // ... + + // 构造要发送的消息内容 + String content = "服务端广播消息: " + message; + + // 使用SimpMessagingTemplate发送消息给所有订阅了"/topic/all"目标的客户端 + messagingTemplate.convertAndSend("/topic/all", content); + + return Result.success("广播消息发送成功"); + } + + /** + * 点对点发送消息 + * + * @param userId 用户ID + */ + @PostMapping("/sendToUser/{userId}") + public Result sendToUser(@PathVariable Long userId, String message) { + log.info("【点对点请求接收】用户:{};消息:{}", userId, JSONUtil.toJsonStr(message)); + // 发送主题目的(destination)= /user/{userId}/message + messagingTemplate.convertAndSendToUser(String.valueOf(userId), "/message", message); + return Result.success("点对点消息发送成功"); + } + +} diff --git a/src/test/java/com/youlai/system/controller/WebsocketControllerTest.java b/src/test/java/com/youlai/system/controller/WebsocketControllerTest.java new file mode 100644 index 00000000..488d648f --- /dev/null +++ b/src/test/java/com/youlai/system/controller/WebsocketControllerTest.java @@ -0,0 +1,42 @@ +package com.youlai.system.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +class WebsocketControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Test + void testSendToAll() throws Exception { + String message = "Hello! I'm server. This is a topic message."; + + mockMvc.perform( + post("/messages/sendToAll") + .param("message", message) + ) + .andExpect(status().isOk()); + } + + @Test + void testSendToUser() throws Exception { + + Long userId = 2L;// 系统管理员用户ID=2 + + mockMvc.perform(post("/messages/sendToUser/{userId}", userId) + .param("message", "Hello! I'm server. This is a point-to-point message.") + ) + //.content(JSONUtil.toJsonStr(webSocketMessage)) + //.contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + } +} \ No newline at end of file