spring boot + websocket
首先,pom文件引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.3.5.RELEASE</version>
</dependency>
然后,服务端创建MyWebSocket,因为spring boot提供了@ServerEndpoint注解,大大减少了配置过程。
现在只需要这样实现即可:
@ServerEndpoint("/websocket")
@Component
public class BlockWebSocket {
//建立连接时会调用此方法
@OnOpen
public void onOpen(Session session){.......};
//连接关闭时会调用此方法
@OnClose
public void onClose(){.....};
//收到客户端消息后调用此方法
@OnMessage
public void onMessage(String message, Session session){....};
//发生错误时会调用此方法
@OnError
public void onError(Session session, Throwable error){...};
//还有一些其他方法,可供业务调用,例如 广播消息等等,详细的可以去查询官网
}
这样服务端的配置就好了。
接下来是前端websocket的配置,通常是在js内配置
let websocket;
if ('WebSocket' in window) {
console.log("智能节点正在测试链接环境......");
websocket = new WebSocket("ws://localhost:8082/websocket");
console.log("webSocket环境正确,正在创建锚点,链接中...");
} else if ('MozWebSocket' in window) {
console.log("环境异常,无法链接..请确认环境..");
websocket = new MozWebSocket("ws://echo");
} else {
console.log("智能节点正在测试链接环境......");
websocket = new SockJS("http://127.0.0.1:8080/websocket");
console.log("SockJS环境正确,正在创建锚点,链接中...");
}
websocket.onopen = function (evnt) {
console.log("链接服务器成功!", evnt.data);
};
websocket.onmessage = function (evnt) {
console.log('收到消息:', evnt.data);
};
websocket.onerror = function (evnt) {
console.log('出现错误了:'+evnt.data);
};
websocket.onclose = function (evnt) {
console.log("与服务器断开了链接!")
};
//这些基本配置就不多说了,这里着重描述一个问题
如果按上面这样配置websocket,是可以成功进行通信的,
但是如果创建websocket的页面刷新了或者关闭了,由于websocket的特性,会导致服务端调用关闭websocket,
但是前端的页面在跳转后,其实连接是还在的,所以就会调用到onerror这个方法,出现错误,服务端就会报错。
错误如下:
java.io.IOException: java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
Caused by: java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
所以,应该控制页面刷新的时候,主动关闭掉此页面的websocket连接。这样就不会提示此错误了。
如何控制?使用js的页面加载刷新的函数即可。如下:
window.onbeforeunload = function(){ websocket.close(); }
这样就解决了如何使服务端不报错的问题。
附:
但是,我想要实现将用户第一次连接的websocket保存下来,不让它断开连接。起初是想把websocket 存进redis内,进行保存。但是发现每次session创建的id都是不同的,无法确定key值,这个想法流产了。
后来,想到一个新思路。使用拦截器,对websocket进行拦截,每次创建新的websocket前,都去redis上扫描一遍,是否该用户已经创建了一个连接,如果已经存在了,那么就把它取出来,而不是重新创建。
但是这个方法还没尝试过。尝试后会再发一篇博文。