springboot+websocket+rabbitmq整合实现消息实时
SpringBoot+WebSocket+RabbitMQ整合实现消息实时
========>可能影响项目运行,访问不到静态资源文件,整合WebSocket也可参考:
https://www.cnblogs.com/yu-si/articles/15075737.html
WebSocket+RabbitMQ基于Spring boot实现
1.配置
maven导包
SpringBoot 与webSocket的关联
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
SpringBoot与Rabbit MQ的关联
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
配置application.yml文件
spring:
rabbitmq:
host: 127.0.0.1
username: guest
password: guest
#虚拟主机
virtual-host: /
port: 5672
编写RabbitMQ服务端
配置服务端的config
@Configuration
public class SendConfig {
@Bean("queue")
public Queue queueMsg(){
return new Queue("queue");
}
@Bean("exchange")
public TopicExchange exchange(){
return new TopicExchange("exchange");
}
@Bean
Binding bindingExchangeAndQueuemsg(@Qualifier("queue") Queue queue, @Qualifier("exchange") TopicExchange exchange){
return BindingBuilder.bind(queue).to(exchange).with("a");
}
}
编写服务端的Controller
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller {
@Autowired
private AmqpTemplate amqpTemplate;
@RequestMapping("/send")
public void SennerMsg(String msg){
amqpTemplate.convertAndSend("exchange","a",msg);
}
}
到这启动MQ后运行程序便可以看到有一个新的邮件
或者用命令查看
编写MQ的客户端(与WebSocket结合)
配置Websocket—做请求拦截
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map;
public class Hank implements HandshakeInterceptor{
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
String jspCode = ((ServletServerHttpRequest) request).getServletRequest().getParameter("jspCode");
if (jspCode != null) {
map.put("jspCoe", jspCode);
} else {
return false;
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
}
配置Websocket的Handler
@Component
public class MyWebSocketHandler implements WebSocketHandler {
private static final Map<String ,WebSocketSession> userMap=new HashMap<>();
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
String jspCode = (String )webSocketSession.getAttributes().get("jspCode");
//if(userMap.get(jspCode)==null){
System.out.println(jspCode);
userMap.put(jspCode,webSocketSession);
//}
}
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
}
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
}
@Override
public boolean supportsPartialMessages() {
return false;
}
public void sendMsgToJsp(final TextMessage message, String type) throws Exception{
Iterator<Map.Entry<String ,WebSocketSession>> it=userMap.entrySet().iterator();
while (it.hasNext()){
final Map.Entry<String ,WebSocketSession> entry=it.next();
System.out.println(entry.getValue().isOpen());
System.out.println(entry.getKey().contains(type));
if(entry.getValue().isOpen()&&entry.getKey().contains(type)){
new Thread(new Runnable() {
@Override
public void run() {
try {
if(entry.getValue().isOpen()){
entry.getValue().sendMessage(message);
}
}catch (IOException e){
e.printStackTrace();
}
}
}).start();
}
}
}
}
配置WebSocket的config
@Component
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Resource
private MyWebSocketHandler handler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(handler, "/wsMy").addInterceptors(new HandshakeInterceptor() {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
String jspCode = ((ServletServerHttpRequest) request).getServletRequest().getParameter("jspCode");
if (jspCode != null) {
map.put("jspCode", jspCode);
} else {
return false;
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
}
});
}
}
配置客户端的cortorller(二者关联的部分)
@Autowired
public MyWebSocketHandler handler;
@RabbitListener(queues = "queue")
public void Recive(String msg) throws Exception{
handler.sendMsgToJsp(new TextMessage(msg), "A");
}
到此便可以启动测试了
另附上前端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<script type="text/javascript">
//1.创建websocket客户端
var wsServerUrl = 'ws://127.0.0.1/';
var limitConnect = 3; // 断线重连次数
var timeConnect = 0;
webSocketInit(wsServerUrl);
//socket初始化链接
function webSocketInit(wsServerUrl) {
// 首先判断是否 支持 WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:80/wsMy?jspCode=AA");
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:80/wsMy?jspCode=AA");
} else {
websocket = new SockJS("ws://localhost:80/wsMy?jspCode=AA");
}
// 打开连接时
websocket.onopen = function (event) {
console.log("已连接TCP服务器");
};
// 收到消息时
websocket.onmessage = function (event) {
console.log("收到一条消息" + event.data);
alert(event.data);
};
websocket.onerror = function (event) {
console.log("服务器报错:");
reconnect()
};
websocket.onclose = function (event) {
console.log('服务器已经断开');
reconnect()
};
// 重连
function reconnect(wsServerUrl) {
// lockReconnect加锁,防止onclose、onerror两次重连
if (limitConnect > 0) {
if (localStorage.getItem('lockReconnect') != true) {
localStorage.setItem("lockReconnect", 1);
limitConnect--;
timeConnect++;
console.log("第" + timeConnect + "次重连");
// 进行重连
setTimeout(function () {
webSocketInit(wsServerUrl);
localStorage.removeItem("lockReconnect");
}, 2000);
}
} else {
console.log("TCP连接已超时");
}
}
// 心跳 * 回应
setInterval(function () {
websocket.send('');
}, 1000 * 100);
}
</script>
</html>
原文链接:https://blog.csdn.net/lilin0800/article/details/80884950
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)