1. 说明
websocket是一个全双工的网络协议,可以双向发送消息或接收消息,对于服务端与客户端之间的通信或者客户端相互通信十分友好
概念不多说,下面就来搭建一个实际的工程
2. 工程搭建
这里的工程搭建springboot结合spring来使用,整合spring的工程;其余的方法可以参见
websocket种工程实现办法
2.1. 引入依赖
1 2 3 4 5 6 7 8 9 10 11
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency>
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency> </dependencies>
|
2.2. 配置 JavaConfig
Java中主要有两个地方关于websocket的配置
- 一处是实现
HandshakeInterceptor
,用于在客户端与websocket建立握手和挥手的时候调用的函数
- 握手前的处理
beforeHandshake
可以用来权限校验等
- 握手后的处理
afterHandshake
- 另一处是实现
WebSocketHandler
,用于在客户端与服务端建立session之后调用的函数,主要包括
- 连接成功的方法
afterConnectionEstablished
- 处理消息的方法
handleMessage
- 处理异常的方法
handleTransportError
- 连接关闭的方法
afterConnectionClosed
我们主要方法是handleMessage
处理消息会每次调用,handleTransportError
在错误的时候调用,其余的均调用一次
第一次的调用流程为 HandshakeInterceptor#beforeHandshake()
-> HandshakeInterceptor#afterHandshake()
->WebSocketHandler#afterConnectionEstablished()
->WebSocketHandler#handleMessage()
2.2.1. 配置HandshakeInterceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Component public class KHandshakeInterceptor implements HandshakeInterceptor {
@Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { System.out.println("握手开始"); Map<String, String> paramMap = HttpUtil.decodeParamMap(request.getURI().getQuery(), "utf-8"); String uid = paramMap.get("token"); if (StrUtil.isNotBlank(uid)) { attributes.put("token", uid); System.out.println("用户 token " + uid + " 握手成功!"); return true; } System.out.println("用户登录已失效"); return false; }
@Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { System.out.println("握手完成"); }
}
|
2.2.2. 配置HandshakeInterceptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| @Component public class KWebSocketHandler extends TextWebSocketHandler {
private static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>();
@Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { Object token = session.getAttributes().get("token"); if (token != null) { SESSION_POOL.put(token.toString(), session); } else { throw new RuntimeException("用户登录已经失效!"); } }
protected void handleTextMessageBak(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload();
Object token = session.getAttributes().get("token"); System.out.println("server 接收到 " + token + " 发送的 " + payload); session.sendMessage(new TextMessage("server 发送给 " + token + " 消息 " + payload + " " + LocalDateTime.now().toString())); }
@Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); String[] split = payload.split("\\|"); String toUser = split[0]; String msg = split[1]; Object token = session.getAttributes().get("token"); System.out.println("server 接收到 " + token + " 发送的 " + payload); WebSocketSession toSession = SESSION_POOL.get(toUser); if (toSession == null) { session.sendMessage(new TextMessage("用户不在线")); } else { toSession.sendMessage(new TextMessage(token+"|给你发来消息:"+msg)); } }
@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { Object token = session.getAttributes().get("token"); if (token != null) { SESSION_POOL.remove(token.toString()); } }
}
|
2.2.3. websocket 配置文件配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer {
@Autowired private KWebSocketHandler socketHandler; @Autowired private KHandshakeInterceptor handshakeInterceptor;
@Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry .addHandler(socketHandler, "ws") .addInterceptors(handshakeInterceptor) .setAllowedOrigins("*"); } }
|
2.2.4. springboot项目启动
1 2 3 4 5 6
| @SpringBootApplication public class D118WebSocketApp { public static void main(String[] args) { SpringApplication.run(D118WebSocketApp.class, args); } }
|
前端工程搭建
暂时没处理,vue项目参考https://blog.csdn.net/thmail/article/details/104064921