SpringBoot配置WebSocket

Java框架

浏览数:272

2019-1-23

简介

WebSocket是一种在单个TCP连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

既然是一个长连接,那么对于比较时效性(如聊天)或者需要推送的场景就可以使用WebSocket来实现,服务端不再是等待客户端的请求而可以主动推送消息给客户端。同时也减少了资源的开销,因为之前通过HTTP的做法通常都是轮询来实现时效性,这种做法需要不断发起HTTP请求,而使用WebSocket长连接减少了连接的开销,建立连接之后只关心数据本身。

基于SpringBoot的WebSocket支持

Spring Websocket介绍

Spring WebSocket通过注册不同WebSocketHandler来处理不同的消息通道,消息处理具体在WebSocketHandler里面实现,通常都是通过实现AbstractWebSocketHandler类来自定义自己的处理器。

maven依赖

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

配置&使用

  • WebSocketConfig
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 注册自定义消息处理,消息路径为`/ws/foo`
        registry.addHandler(new FooWebSocketHandler(),"/ws/foo").setAllowedOrigins("*");

    }
}

  • 自定义处理器 FooWebSocketHandler
public class FooWebSocketHandler extends TextWebSocketHandler {

    private final static List<WebSocketSession> sessions = new ArrayList<>();

    public static List<WebSocketSession> allSessions(){
        return new ArrayList<>(sessions);
    }


    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //在这里自定义消息处理...
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        
        //保存所有会话
        sessions.add(session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {

        if(!sessions.isEmpty()){
            // remove session after closed
            for (Iterator<WebSocketSession> iterator = sessions.iterator();iterator.hasNext();){

                WebSocketSession s = iterator.next();

                if(session.getId().equals(s.getId())){
                    iterator.remove();
                }
            }
        }
    }
}
  • 实现简单消息推送给所有在线用户
for (WebSocketSession session : FooWebSocketHandler.allSessions()) {
    try {
        TextMessage message = new TextMessage("${message body}").getBytes());
        if(session.isOpen()){
            session.sendMessage(message);
        }
    } catch (IOException e) {
        throw new RuntimeException(e.getMessage(),e);
    }
}
  • 客户端与服务端连接交互(JavaScript为例)
var ws = new WebSocket('ws://localhost:8080/ws/foo')

ws.onmessage = function(event) {
  var data = event.data;
  console.log(data)
};
  • nginx配置WebSocket方向代理
http {

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    upstream websocket {
        server localhost:8080;
    }
    
    server{
        location ~ /ws {
            proxy_pass http://websocket;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

参考

原文地址:https://www.jianshu.com/p/6b6b68657d05