一、WebSocket
1、什么是websocket
是HTML5的一种新的协议,WebSocket是真正实现了全双工通信的服务器向客户端的互联网技术,是单个TCP连接上进行全双工通信的协议。
2、与socket、HTTP的区别
与socket的区别
WebSocket拥有完整的应用层协议,包含一套标准的API
Socket是一组接口,是应用层与TCP/IP协议通信的中间软件抽象层
与HTTP的区别
http是短链接,请求之后会关闭连接。
WebSocket是长连接,只需要通过一次请求初始化连接,然后所有的请求和响应都是通过这个TCP连接进行通信。
二、代码应用
1、服务端
pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
拦截器
负责在握手之前,处理客户端的URL请求
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.util.Map;
@Slf4j
public class MyWebSocketInterceptor extends HttpSessionHandshakeInterceptor {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 握手之前,做参数处理
* @param request the current request
* @param response the current response
* @param wsHandler the target WebSocket handler
* @param attributes the attributes from the HTTP handshake to associate with the WebSocket
* session; the provided attributes are copied, the original map is not used.
* @return
* @throws Exception
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
logger.info("[MyWebSocketInterceptor#BeforeHandshake] Request from " + request.getRemoteAddress().getHostString());
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
String id = serverHttpRequest.getServletRequest().getParameter("id");
attributes.put("id", id);
}
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
logger.info("[MyWebSocketInterceptor#afterHandshake] Request from " + request.getRemoteAddress().getHostString());
}
}
Handler
负责websocket的消息处理、关闭等操作
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class MyWebsocketHandler extends AbstractWebSocketHandler {
public static final Map<String, WebSocketBean> webSocketBeanMap;
/**
* 仅用用于标识客户端编号
*/
private static final AtomicInteger clientIdMaker;
static {
webSocketBeanMap = new ConcurrentHashMap<>();
clientIdMaker = new AtomicInteger(0);
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// 当WebSocket连接正式建立后,将该Session加入到Map中进行管理
Map<String, Object> attributes = session.getAttributes();
WebSocketBean webSocketBean = new WebSocketBean();
webSocketBean.setWebSocketSession(session);
webSocketBean.setClientId(clientIdMaker.getAndIncrement());
webSocketBean.setId(attributes.get("id").toString());
webSocketBeanMap.put(session.getId(), webSocketBean);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
//当连接关闭后,从Map中移除session实例
webSocketBeanMap.remove(session.getId());
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws E