利用WebSocket实现实时通知

在编写小说网站时,突发奇想:作者发布章节后,是不是粉丝应该接收到作者发布章节的消息通知呢。以下就是一个测试案例:

添加pom.xml文件依赖:

XML 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

以上只给了websocket依赖,实际还要添加mysql依赖,以及配置application中数据库:

XML 复制代码
spring.datasource.url=
spring.datasource.driver-class-name=
spring.datasource.username=
spring.datasource.password=

接下来就创建一个配置类启用 WebSocket 消息代理:

java 复制代码
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;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 定义 WebSocket 端点,前端通过此连接
        registry.addEndpoint("/ws")
                .setAllowedOriginPatterns("*") // 允许跨域(生产环境建议限制域名)
                .withSockJS(); // 支持 SockJS 回退
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 客户端订阅地址前缀(前端从这里订阅)
        registry.enableSimpleBroker("/topic");
    }
}

监听作者发布章节事件

定义事件类

java 复制代码
public class ChapterPublishedEvent {
    private Long authorId;
    private String chapterTitle;

    // 构造方法、Getter/Setter
}
在发布章节的方法中触发事件
java 复制代码
@RestController
public class ChaptersController {

@Autowired
NovelsMapper mapper;

@Autowired
private ApplicationEventPublisher eventPublisher;

    @RequestMapping("chapter")
    String insert(HttpServletRequest request){
// 触发事件
        eventPublisher.publishEvent(new ChapterPublishedEvent(1, "文章名"));
        return "chapter:" + request.getServerPort();
    }
}

推送消息给关注者

监听事件并发送消息

java 复制代码
import com.lxy.other.dao.UserAuthMapper;
import com.lxy.other.vo.ChapterPublishedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Async; // 可选异步
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Component
public class ChapterPublishListener {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private UserAuthMapper userAuthMapper; // 自定义服务,用于查询关注者

    @EventListener
    @Async // 异步处理(可选,需在启动类添加 @EnableAsync)
    public void handleChapterPublishedEvent(ChapterPublishedEvent event) {
        Long authorId = event.getAuthorId();
        // 查询所有关注该作者的用户的ID
        List<Long> followerIds = new ArrayList<>(Arrays.asList(2L, 3L));
        // 向每个关注者推送消息
        followerIds.forEach(followerId -> {
            String destination = "/topic/user/" + followerId + "/notifications";
            messagingTemplate.convertAndSend(destination, "作者发布了新章节:" + event.getChapterTitle());
        });
    }
}

前端订阅通知

使用 SockJS 和 Stomp.js 连接 WebSocket 并订阅频道:

html 复制代码
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<head>
    <title>WebSocket通知</title>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.6.1/dist/sockjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>

<script>
    // 1. 连接 WebSocket
    const socket = new SockJS('http://127.0.0.1:8002/ws');
    const stompClient = Stomp.over(socket);

    // 2. 订阅通知
    stompClient.connect({}, () => {
        const userId = 2; // 替换为实际用户ID
        stompClient.subscribe(`/topic/user/${userId}/notifications`, (message) => {
            console.log('收到通知:', message.body);
            alert(message.body);
        });
    }, (error) => {
        console.error('连接失败:', error);
    });
</script>
</body>
</html>

效果图:

发送触发事件的请求。

这个时候就可以自定义 页面样式了

相关推荐
苏渡苇35 分钟前
Spring Insight:跨服务调用链路是怎么串起来的?
spring boot·后端·spring·系统监控·apm
溜达的大象36 分钟前
管家婆远程访问实战:SQL Server 2022配置、PC分机端修改与固定TCP连接
网络·网络协议·tcp/ip
\光辉岁月/1 小时前
15.JavaSE-网络
java·开发语言·网络
星恒讯工业路由器1 小时前
5G RedCap、eRedCap与LTE Cat-1bis:中低速物联网的“三国杀“与选型指南
网络·智能路由器·工业路由器·工业物联网·5g redcap·lte cat-1bis·eredcap
艾芯微科技1 小时前
ETA1637S2G|钰泰同步升压 LED 背光驱动 SOT23-6,0.1% 超低占空比 PWM 调光
网络·单片机·嵌入式硬件·集成测试·51单片机
JosieBook2 小时前
【多线程】两台机器同时抢一个字典:一次并发 Bug 的排查
java·网络·bug
Multipath7122 小时前
以多链路聚合为通信底座,让低空飞行器“连得上、传得快、飞得稳、管得住”
网络·5g·安全·智能路由器·实时音视频
白露与泡影2 小时前
Spring Boot 实现验证码:Hutool-captcha、AJ-Captcha、EasyCaptcha 到底怎么选?
java·spring boot·后端
seconp2 小时前
基于Spring Boot和Vue 3的智慧旅游网站:住宿预订、行程规划与千问接入
vue.js·spring boot·毕业设计·软件工程·课程设计·旅游·毕设
vx_bisheyuange2 小时前
基于SpringBoot的校园数字化图书馆系统
spring boot·毕业设计