Spring Boot 整合 Web Socket

POM

websocket starter

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

Java bean 配置

websocket 配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
 
@Configuration
@EnableWebSocket
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        //支持 @ServerEndpoint  注解
        return new ServerEndpointExporter();
    }
}

这个bean的注册, 用于扫描带有@ServerEndpoint的注解成为websocket,如果你使用外置的tomcat就不需要该配置文件

ServerEndpoint

@ServerEndpoint 注解的类是无法直接使用 @Autowired 的, 因为@ServerEndpoint表明当前类是websocket的服务端点, 在spring容器启动时会初始化一次该类, 当有新的websocket连接的时候, 也会进行该类实例的创建 (每一次连接时都会创建一个实例)

@Component
@ServerEndpoint("/websocket")
public class WebSocket {
 
    @OnOpen
    public void onOpen( Session session){
        log.info("有新的连接: {}", session);
    }
    
    @OnMessage
    public void onMessage(String message){
        log.info("有新消息: {}", message);
    }
    
    @OnClose
    public void onClose(Session session){
        log.info("连接关闭: {}", session);
     
    }
    
    @OnError
    public void onError(Session session, Throwable throwable){
        log.info("连接出现异常: {}", throwable);
    }
    
}

注意:

  1. ServerEndpoint 是多实例创建的,有用户连接时就会创建一个新的端点实例, 与Spring 容器单例模式冲突的, 无法使用 @Autowired 注入的!
  2. 路径 /websocket 也会经过 Spring Sencurity 过滤, 请注意权限过滤问题

访问参数 & 上下文绑定

Map<String, List<String>> params = session.getRequestParameterMap();
List<String> tokenParam = params.get("token");
List<String> device_idParam = params.get("deviceId");
 
 //绑定属性
Map<String, Object> userProperties = session.getUserProperties();
userProperties.put(MODEL_KEY, model);
if (CollUtil.isNotEmpty(tokenParam)){
//            String s = tokenParam.get(0);
}
if (CollUtil.isNotEmpty(device_idParam)){
    userProperties.put(DEVICE_ID_KEY, device_idParam.get(0));
}
userProperties.put(SESSION_ID, UUID.fastUUID().toString());

提高并发

异步执行

异步调用几乎是处理高并发Web应用性能问题的万金油 在Spring Boot中,我们只需要通过使用@Async注解就能简单的将原来的同步函数变为异步函数

@Async
public Future<String> doTaskOne() throws Exception {
 
}

@Async注解能够生效,还需要在Spring Boot的主程序中配置@EnableAsync