当前位置:   article > 正文

WebSocket后端搭建,避坑指南

websocket后端

网上有很多写WebSocket搭建的案例,我这里也是主要记录一下,我在部署WebSocket上踩到的坑。案例主要是给自己记录一下
我这里是用SpringBoot 搭建的WebSocket
首先就是配置类的代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 *  WebSocket配置类
 */


@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在之后就是WebSocket的核心代码,消息的接收和连接的建立都是基于这个类

// 这里我写的是@Service 是因为我把这个类写在Service层
@Service
@ServerEndpoint("/webSocket/{userId}")
public class WebSocketServerImp{
/**
	这里解释一下为什么要加ApplicationContext 因为spring是单例设计而websocket 是一个多实例类,每次建立连接都会有一个新的webSocket类所以@Autowired这类自动注入注解是不起效果的,所以每次需要通过上下文来获取实例
*/
private static ApplicationContext applicationContext;
 /**concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。*/
private static ConcurrentHashMap<Long,Session> webSocketMap = new ConcurrentHashMap<>();
 public static void setApplicationContext(ApplicationContext applicationContext) {
        WebSocketServerImp.applicationContext = applicationContext;
    }
    /**
     * 连接建立成
     * 功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") Long userId) {
        webSocketMapper = applicationContext.getBean(WebSocketMapper.class);
        this.userId = userId;
        if(webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            //加入set中
            webSocketMap.put(userId,session);
        }else{
            //加入set中
            webSocketMap.put(userId,session);
        }
        
         }
    /**
     * 连接关闭
     * 调用的方法
     */
    @OnClose
    public void onClose() {

    }
    /**
     * 收到客户端消
     * 息后调用的方法
     * @param jsonMessage
     * 客户端发送过来的消息
     **/
    @OnMessage
    public void onMessage(String jsonMessage) {
    
        }
        /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
        error.printStackTrace();
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

因为我们在@ServerEndpoint这个类里面加了private static ApplicationContext applicationContext;,也有set方法那我们也应该在哪里set呢?答案是启动类,从启动类获取上下文,然后set
启动类代码:

@SpringBootApplication
@MapperScan("com.xxx.server.mapper")
public class YebApplication extends SpringBootServletInitializer {
    public static void main(String[] args) {
        ConfigurableApplicationContext applicationContext = SpringApplication.run(YebApplication.class, args);
        WebSocketServerImp.setApplicationContext(applicationContext);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

webSocket 的代码到这里就结束了。下面来说一下有那些坑
1、需不需要加@Service或@Component?网络上有些人说@ServerEndpoint本身就有@Component我尝试不要这种bean注册注解,我的@ServerEndpoint是没有自带bean注册注解的,可能是版本问题吧,我觉得是需要加的加了规范一点,至少让别人看你类的时候也会舒服一点
2、@OnError 这个类里面的形参必须要有Throwable error这个形参,不然你的@ServerEndpoint会注册失败
3、@OnClose 这个类里面的形参不能有任何参数,不然就是注册失败,这个坑我踩了很久!
4、在@ServerEndpoint中@Autowired这类自动注入注解失败问题,这个问题我在上面的代码注释里面也说了,主要原因就是spring和websocket犯冲,一个是单例,一个是多例

最近又踩了一个坑,WebSocket connection to XXXX,在csdn上copy的代码,上面有那种多余的依赖包,我添加上去之后,在webSocket的类上加上@Component这类的注解就是报错,不添加的话前端就会连接不到WebSocket,依赖的话就我上面写的就够了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/787257
推荐阅读
相关标签
  

闽ICP备14008679号