最近因为有需要统计实时客流信息的需求,考虑到使用轮询请求开销大,所以想整合websocket使用。
但是却一直报404错误,路径项目,后端websocket代码怎么改都没用,网上说是tomcat问题,需要tomcat8才能支持websocket,因为我的springboot是1.5.6版本,刚开始在maven配置将内置tomcat改成8.0以上还是不行,有尝试了很多种方法,最后直接将springboot项目重构升级到2.0.7+jdk1.8版本,才成功解决(因为生产环境是jdk1.7,而且springboot1.5版本和2.0改动较大,起初不想改动版本)。导致踩了很多坑。
错误解决,将websocket如何整合顺道写下:
首先创建websocket的config类,注入ServerEndpointExporter(使用外置tomcat就无需注入)。注册了这个类之后就会对@ServerEndpoint声明类进行注入,成websocket服务类,进行监听。
(MySpringConfigurator类是为了使WebSocketServer类能够注入其他bean(如图中RedisService的bean),因为websocket注册的bean默认是自己管理,没有托管给spring,所以,此类是为了将websocket的bean托管给spring容器。)
@Configuration
@ConditionalOnWebApplication
public class WebSocketConfig {
//使用boot内置tomcat时需要注入此bean
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public MySpringConfigurator mySpringConfigurator() {
return new MySpringConfigurator();
}
}
/**
* 以websocketConfig.java注册的bean是由自己管理的,需要使用配置托管给spring管理
*/
public class MySpringConfigurator extends ServerEndpointConfig.Configurator implements ApplicationContextAware {
private static volatile BeanFactory context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
MySpringConfigurator.context = applicationContext;
}
@Override
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
return context.getBean(clazz);
}
}
创建websocketServer类(太长了,忽略@onopen等方法)
/*
websocket所需注解,设置监听路径等,此注解会为每一个连接请求创建一个point实例对象,
此注解会将编解码成一个websocket服务,url是发布路径。
*/
@Component
@ServerEndpoint(value = "/webSocket/{sid}", configurator = MySpringConfigurator.class)
public class WebSocketServer {
@Autowired
private RedisService redisService;
private Session session;//每个客户端锁相对应的session,服务端根据session和客户端进行数据交互
private String sid = "";
private static CopyOnWriteArraySet<WebSocketServer> copyOnWriteArraySet
= new CopyOnWriteArraySet<WebSocketServer>();//存储每个客户端连接
....实现@onopen等方法...
}
前端页面网上很多,这里不放了。