SpringBoot使用WebSocket实现前后端消息推送

文章出处:http://www.3kkg.com/1073

WebSocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。与正常的http请求不同的是,WebSocket在浏览器和服务器之间只需要完成一次握手即可创建了一个持久性的长连接,通过这个长连接实现双向的数据传输。

本文只介绍后端SpringBoot如何使用WebSocket,前端部分使用:WebSocket在线测试地址 中的工具进行效果测试。

项目pom文件中引入WebSocket相关的依赖

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

SpringBoot是通过ServerEndpointExporter来扫描@ServerEndpoint注解声明的类从而实现WebSocket相关服务的,所以我们需要手动配置一个config类来在Spring上下文中提供ServerEndpointExporter。需要注意的是,如果你使用的是外部容器部署(如SpringBoot打war包并使用外置tomcat部署 等)则不需要这个config类来提供ServerEndpointExporter,因为此时SpringBoot默认将扫描@ServerEndpoint注解的行为交给了外部容器处理。

复制代码/**
 * Spring上下文注入ServerEndpointExporter
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

接下来就是编写WebSocket的服务类及相关的业务逻辑了,我这里做了一个简单的样例

复制代码/**
 * 测试WebSocket
 */
@ServerEndpoint("/test")
@Component
@Slf4j
public class TestWebSocket {

    /**
     * concurrent包的线程安全Set
     * 用来存放每个客户端的连接会话session
     */
    private static CopyOnWriteArraySet<Session> sessionSet = new CopyOnWriteArraySet<>();

    /**
     * 在客户初次连接时触发
     * 这里会为客户端创建一个session,这个session并不是我们所熟悉的httpsession
     *
     * @param session
     */
    @OnOpen
    public void onOpen(Session session) {
        log.info(session.getId() + "加入!当前在线人数为" + getOnlineCount());
        sessionSet.add(session);
        groupMessage(session.getId() + "加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 在客户端与服务器端断开连接时触发
     */
    @OnClose
    public void onClose(Session session) {
        log.info(session.getId() + "连接关闭!当前在线人数为" + getOnlineCount());
        sessionSet.remove(session);
        groupMessage(session.getId() + "连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param session
     * @param message
     */
    @OnMessage
    public void onMessage(Session session, String message) {
        log.info(session.getId() + "说" + message);
        groupMessage(session.getId() + "说" + message);
    }

    /**
     * 给某个会话发送消息
     *
     * @param session
     * @param message
     */
    public static void sendMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 给当前在线的人群发消息
     *
     * @param message
     */
    public static void groupMessage(String message) {
        for (Session session : sessionSet) {
            sendMessage(session, message);
        }
    }

    /**
     * 获取当前连接数
     *
     * @return
     */
    public static synchronized int getOnlineCount() {
        return sessionSet.size();
    }

}

WebSocket会根据具体的行为分别调用@OnOpen、@OnClose、@OnMessage等注解标记的方法,消息的发送以及连接都是通过Session对象实现的(这里的Session跟我们之前普通web服务里面的HttpSession不同

为了实现群发消息,我这里通过一个线程安全的CopyOnWriteArraySet来讲每个连接的Session存储起来,方便后续消息的推送。

测试效果(上述样例中WebSocket的连接地址为:ws://127.0.0.1:8080/test 跟正常的web请求地址基本类似,只是开头的http换成了ws)

完整的demo见:https://gitee.com/floow/blog-demo demo17

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值