WebSocket后端搭建,避坑指南

9 篇文章 0 订阅

网上有很多写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();
    }
}

在之后就是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();
    }

}

因为我们在@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);
    }
}

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,依赖的话就我上面写的就够了。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值