网上有很多写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犯冲,一个是单例,一个是多例文章来源:https://www.toymoban.com/news/detail-419024.html
最近又踩了一个坑,WebSocket connection to XXXX,在csdn上copy的代码,上面有那种多余的依赖包,我添加上去之后,在webSocket的类上加上@Component这类的注解就是报错,不添加的话前端就会连接不到WebSocket,依赖的话就我上面写的就够了。文章来源地址https://www.toymoban.com/news/detail-419024.html
到了这里,关于WebSocket后端搭建,避坑指南的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!