SpringBoot整合WebSocket

refer:https://blog.csdn.net/z1790424577/article/details/81011416
https://blog.csdn.net/zxwu_1993/article/details/81034087



前言

思考:像这样的消息功能怎么实现?
如果网页不刷新,服务端有新消息如何推送到浏览器?
解决方案,采用轮询的方式。即:通过js不断的请求服务器,查看是否有新数据,如果有,就获取到新数据。
这种解决方法是否存在问题呢?
当然是有的,如果服务端一直没有新的数据,那么js也是需要一直的轮询查询数据,这就是一种资源的浪费。
那么,有没有更好的解决方案? 有!那就是采用WebSocket技术来解决。

在这里插入图片描述

一、什么是WebSocket

WebSocker是一个保持web客户端与服务器长链接的技术,它实现了浏览器与服务器全双工通信(full-duplex)。
这样在两端通信过程中 ,任意一端如果有消息想 想发送给对端时,无需等待对端发送一个请求了。
它是一种在单个TCP连接基础上 进行全双工通讯协议,一开始的握手需要借助HTTP请求完成。

什么是全双工?
全双工(Full Duplex)是通讯传输的一个术语。通信允许数据在两个方向上同时传输,它在能力上相当
于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指
A→B的同时B→A,是瞬时同步的。

好处:
它实现了浏览器与服务器全双工通信,它能够实现Web浏览器和服务器之间的异步通信。能更好的节省服务器资源和带宽并达到实时通讯。
在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实时性优势明显。

WebSocket 请求响应客户端服务器交互图:
在这里插入图片描述

浏览器中查看建立连接的过程:
在这里插入图片描述

二、SpringBoot中使用WebSocket步骤

1、导入依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、编写消息处理类
较简单的方式就是直接继承AbstractWebSocketHandler,并覆写其中的处理方法,或者继承TextWebSocketHandler.

/**
 * websocket 消息处理类
 *
 * @author liangqi
 * @date 2021/5/23 0:07
 */
public class MySocketHandler extends TextWebSocketHandler {
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("获取到消息 >> " + message.getPayload());
        session.sendMessage(new TextMessage("消息已收到"));
        if (message.getPayload().equals("10")) {
            for (int i = 0; i < 10; i++) {
                session.sendMessage(new TextMessage("消息 -> " + i));
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Object uuid = session.getAttributes().get("uuid");
        session.sendMessage(new TextMessage("欢迎【" + uuid + "】连接到ws服务"));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("断开连接!");
    }
}

3、编写握手拦截器
在进行三次握手建立连接之前,若需要进行一些操作,如:校验操作。则可以编写一个握手拦截器。

/**
 * 握手拦截器
 * 可以在三次握手建立连接之前,进行拦截。写一些业务逻辑,如;校验等
 *
 * @author liangqi
 * @date 2021/5/23 0:25
 */
@Component
public class MyHandShakeInterceptor implements HandshakeInterceptor {
    /**
     * 握手之前进行判断,若返回false,则不建立链接
     *
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @param webSocketHandler
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
        //将用户id放入socket处理器的会话(WebSocketSession)中
        map.put("uuid", 1001);
        System.out.println("开始握手。。。。。。。");
        return true;
    }

    /**
     * 握手成功,建立连接之后执行
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @param webSocketHandler
     * @param e
     */
    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
        System.out.println("握手成功啦。。。。。。");
    }
}

4、WebSocket的配置类

/**
 * websocket 消息配置类
 *
 * @author liangqi
 * @date 2021/5/23 0:11
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Autowired
    WebSocketHandler handler;

    @Autowired
    private MyHandShakeInterceptor interceptor;

    /**
     * handler 与 请求url进行映射。
     * @param registry
     */
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(handler, "/ws")
            .setAllowedOrigins("*")
            .addInterceptors(interceptor);
    }

    @Bean
    public WebSocketHandler mySocketHandler() {
        return new MySocketHandler();
    }
}

5、测试:
这样,在html页面中可以直接访问这个类配置的url,就可以访问到对应的Handler,从而进行相关逻辑的处理,而不是经过controller层来管理,有了这个类,WebSocketConfig就相当于是controller层了。相关逻辑的处理代码位于自定义的 Handler()中。
可以通过 工具进行测试: http://www.websocket-test.com/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值