1. 引入依赖
在你的Spring Boot项目的pom.xml
中添加以下依赖:
<dependencies>
<!-- Spring Boot Starter Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Spring Boot Starter WebSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
</dependencies>
2. 配置WebSocket
创建一个配置类来设置WebSocket连接端点、STOMP协议和消息传输路径:
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketMessageBrokerConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws") // WebSocket握手端口
.setAllowedOriginPatterns("*") // 设置跨域
.withSockJS(); // 开启SockJS回退机制
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app") // 发送到服务端目的地前缀
.enableSimpleBroker("/topic");// 开启简单消息代理,指定消息订阅前缀
}
}
3. 创建消息处理器
创建一个控制器来处理客户端发送的消息,并将消息广播给订阅了相关主题的客户端:
/**
* 功能描述:
*
* @author Songxianyang
* @date 2024-08-05 17:24
*/
@Controller
@Slf4j
@RequiredArgsConstructor
public class StompController {
private final SimpMessagingTemplate messagingTemplate;
@GetMapping("stomp")
public ModelAndView stomp() {
return new ModelAndView("stomp");
}
/**
* 数据通过前端发送到后端,处理完数据后在响应给前端的订阅者“/topic/public”
* @param chatMessage
* @return
*/
// 这个注解的作用是映射客户端发送到服务器的消息路径
@MessageMapping("/chat.sendMessage")
@SendTo("/topic/public")
public ChatMessage sendMessage(ChatMessage chatMessage) {
return chatMessage;
}
@MessageMapping("/chat.addUser")
@SendTo("/topic/public")
public ChatMessage addUser(ChatMessage chatMessage, SimpMessageHeaderAccessor headerAccessor) {
// 将用户名存储在WebSocket会话中
headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
return chatMessage;
}
/**
* 服务端主动给客户端发送消息
* @return
*/
@GetMapping("s-to-c")
@SendTo("/topic/public")
@ResponseBody
public ChatMessage sToC() {
ChatMessage chatMessage = new ChatMessage();
chatMessage.setContent("西瓜视频");
chatMessage.setSender("Server");
chatMessage.setType(ChatMessage.MessageType.CHAT);
// 发送消息
messagingTemplate.convertAndSend("/topic/public", chatMessage);
return chatMessage;
}
@GetMapping("/html/greeting")
public ModelAndView turnToGreetingPage() {
return new ModelAndView("greeting");
}
@MessageMapping("/greeting")
public String sayGreeting(String name) {
log.info("Message received: {}", name);
return "Hello, " + name;
}
}
4. 创建消息模型
创建一个简单的Java类来表示聊天消息:
/**
* 聊天消息对象
*/
@Data
public class ChatMessage {
/**
* 消息的类型
*/
private MessageType type;
/**
* 消息的内容
*/
private String content;
/**
* 发送者
*/
private String sender;
public enum MessageType {
//普通聊天消息
CHAT,
// 加入聊天
JOIN,
// 离开聊天
LEAVE
}
}
5. 创建前端代码(stomp.html)
在前端(例如使用HTML和JavaScript)中集成WebSocket和STOMP。以下是一个简单的示例:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket-Chat-stomp</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sockjs-client/1.6.1/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
<script>
var stompClient = null;
// 接收消息
function connect() {
var socket = new SockJS('/ws');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
// 客户端订阅服务端消息
stompClient.subscribe('/topic/public', function (message) {
showMessage(JSON.parse(message.body));
});
});
}
// 发送消息
function sendMessage() {
var messageContent = document.getElementById("message").value;
// 往客户端发送消息
stompClient.send("/app/chat.sendMessage", {}, JSON.stringify({
sender: "User",
content: messageContent,
type: 'CHAT'
}));
}
// 展示消息
function showMessage(message) {
var response = document.getElementById("response");
var p = document.createElement("p");
p.appendChild(document.createTextNode(message.sender + ": " + message.content));
response.appendChild(p);
}
// 用户加入
function addUser() {
var userName = document.getElementById('username').value;
if (userName && stompClient) {
var chatMessage = {
sender: userName,
content: userName + "已加入聊天!请注意财产安全",
type: 'JOIN'
};
stompClient.send("/app/chat.addUser", {}, JSON.stringify(chatMessage));
}
}
</script>
</head>
<body onload="connect()">
<div>
<input type="text" id="username" placeholder="Enter your name" />
<button onclick="addUser()">用户加入</button>
<input type="text" id="message" />
<button onclick="sendMessage()">发送信息</button>
</div>
<div id="response"></div>
</body>
</html>
7. yml配置
server:
port: 9999
# servlet:
# context-path: /demo
spring:
freemarker:
request-context-attribute: request
suffix: .html
content-type: text/html
enabled: true
cache: false
charset: UTF-8
allow-request-override: false
expose-request-attributes: true
expose-session-attributes: true
expose-spring-macro-helpers: true
8. 运行应用程序
启动Spring Boot应用程序,并打开你的HTML页面,你应该能够通过WebSocket连接发送和接收消息了。
链接 | 说明 |
---|---|
http://localhost:9999/stomp | 第一个客户端 |
http://localhost:9999/stomp | 第二个客户端 |
http://localhost:9999/s-to-c | 服务端主动给客户端发送消息 |
1.前端
2.用户加入
3.聊天消息
4.服务端主动给客户端发送消息
总结
通过以上步骤,你可以在Spring Boot项目中集成WebSocket和STOMP协议,实现实时的双向通信功能。这是一个基本的示例,你可以根据需要进行扩展和自定义,例如添加更多的消息处理逻辑、安全认证等。