websocket实现一:
使用springboot的配置,实现websocket服务端,需要导入spring websocket的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
创建websocket的配置
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(orderHandler(),"/orderWSServer")
.addInterceptors(new OrderInterceptor()).setAllowedOrigins("*");
}
@Bean
public TextWebSocketHandler orderHandler(){
return new OrderHandler();
}
}
这里需要配置handler与一个拦截器
public class OrderHandler extends TextWebSocketHandler{
public static final HashMap<String, WebSocketSession> userSessionMap;
static {
userSessionMap = new HashMap<>();
}
/**
* 连接成功时候,会触发UI上onopen方法
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("connect to the websocket success......");
Map<String, Object> attributes = session.getAttributes();
String userCode = (String) attributes.get("userCode");
if(userCode != null) {
userSessionMap.put(userCode, session);
}
}
/**
* 在UI在用js调用websocket.send()时候,会调用该方法
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
sendMessageToUsers(message);
}
/**
* 给某个用户发送消息
*
* @param userName
* @param message
*/
public void sendMessageToUser(String userName, TextMessage message) {
}
/**
* 给所有在线用户发送消息
*
* @param message
*/
public void sendMessageToUsers(TextMessage message) {
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
Map<String, Object> attributes = session.getAttributes();
String userCode = (String) attributes.get("userCode");
if(userCode != null) {
userSessionMap.remove(userCode);
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
Map<String, Object> attributes = session.getAttributes();
String userCode = (String) attributes.get("userCode");
if(userCode != null) {
userSessionMap.remove(userCode);
}
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}
public class OrderInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
System.out.println("Before Handshake");
String userCode = ((ServletServerHttpRequest) request).getServletRequest().getParameter("userCode");
System.out.println(userCode);
attributes.put("userCode", userCode);
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
System.out.println("After Handshake");
super.afterHandshake(request, response, wsHandler, ex);
}
}
这里interceptor中可以获取到请求中的信息,在客户端中websocket连接可以携带请求参数。
在js客户端发送请求,增加心跳机制,防止nginx自动断开连接
var heartCheck = {
timeout: 20000,
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
websocket.send("HeartBeat" + new Date());
console.info("客户端发送心跳:" + new Date());
self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
websocket.close();//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, self.timeout)
}, this.timeout)
}
}
var userCode = $("input[name='userCode']").val();
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://192.168.160.152:7003/ycService/orderWSServer?userCode="+userCode);
}
else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function () {
setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function () {
//如果获取到消息,心跳检测重置
heartCheck.reset().start();
setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
setMessageInnerHTML(event.data);
console.log(event);
}
//连接关闭的回调方法
websocket.onclose = function () {
setMessageInnerHTML("WebSocket连接关闭");
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
closeWebSocket();
}