Springboot 整合 WebSocket

一、什么是 WebSocket

WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。

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

单工就是在只允许甲方向乙方传送信息,而乙方不能向甲方传送 。(比喻汽车的单行道。)

(查看更多:全双工——百度百科)

【注】所谓的“浏览器和服务器只需要完成一次握手”,是说在三次握手完成TCP连接后,还会传输一次握手数据;

Springboot 整合 WebSocket_第1张图片

二、WebSocket的特点

WebSocket既然是全双工通信,自然是能实现聊天软件、订阅、游戏等;其特点是:

  • 建立在 TCP 协议之上,处于OSI模型中的应用层,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

三、Springboot 整合 WebSocket

1、pom.xml 引入依赖包

        
        
            org.springframework.boot
            spring-boot-starter-websocket
        

2、暴露 WebSocket 接口

@Slf4j
@Component
@ServerEndpoint(value = "/playBack")
public class WebSocketServerPlayBack {



    /** 记录链接在线数量 **/
    private static final AtomicInteger onlineCount = new AtomicInteger(0);


    /** 存放每个客户端对应的 WebSocketServer 对象 **/
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet<>();


    /** 与某个客户端的连接会话,需要通过它来给客户端发送数据 **/
    private Session session;


    /** 心跳报文 **/
    private static final String HEARTBEAT_PACKETS = "The heartbeat packets";


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        // 加入set中
        webSocketSet.add(this);
        // 在线数加1
        onlineCount.getAndIncrement();
        
    }


    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        // 从set中删除
        webSocketSet.remove(this);
        // 在线数减1
        onlineCount.getAndDecrement();
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("[历史数据回放] - WS 异常断开", session, error);
    }


    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
       if (HEARTBEAT_PACKETS.equals(message)) {
           log.debug("[消息订阅] - 心跳.");
           return;
        }
       // TODO 接收前端入参后的业务处理
     
   }

    /**
     * 群发自定义消息
     */
    public static void sendInfo(String message) {
        for (WebSocketServerPlayBack item : webSocketSet) {
            try {

                item.sendMessage(message);
            } catch (IOException e) {
                log.error("[NVR 数据对接] - 数据推送异常, 数据: [{}].", message, e);
                continue;
            }
        }
    }


    /**
     * 指定会话推送
     * @param message
     */
    public static void sendInfo(Session session, String message) {
        for (WebSocketServerPlayBack item : webSocketSet) {
            try {
                if (null != session && item.session.equals(session)) {
                    item.sendMessage(message);
                }

            } catch (IOException e) {
                log.error("[数据对接] - 数据推送异常, 数据: [{}].", message, e);
                continue;
            }
        }
    }
  
    /**
     * 向链接推送消息
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

}

3、灵活配置 WebSocket ,避免报文太大,接收时报错

@Configuration
public class WebSocketConfig {

    /**
     * 自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     *
     * @return
     */

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

    /**
     * 通信文本消息和二进制缓存区大小
     * 避免对接 第三方 报文过大时,Websocket 1009 错误
     * @return
     */

    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
        // 在此处设置bufferSize
        container.setMaxTextMessageBufferSize(10240000);
        container.setMaxBinaryMessageBufferSize(10240000);
        container.setMaxSessionIdleTimeout(15 * 60000L);
        return container;
    }
}

4、调用接口调试

ws://216.1.1.7:2713/playBack

测试 webSocket 收发小工具:websocket.html

Springboot 整合 WebSocket_第2张图片

 

你可能感兴趣的:(Java基础,springboot,websocket,spring,boot,java)