前言
此文章基于服务端对客户端发送消息教程
采用springboot websocket进行聊天
只需一个配置类就可以完成
本文采用点对点进行发送消息
maven依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>2.4.3</version> </dependency>
配置类
/** * @author wuzhenyong * <p> * WebSocket配置类 */ @Slf4j @Configuration @RequiredArgsConstructor @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { private final ResourceServerTokenServices tokenService; /** * 注册socket端点 * @author wuzhenyong */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 定义websocket端点,ws采用socketjs协议 // setAllowedOriginPatterns解决跨域问题 registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS(); registry.addEndpoint("/ws-test").setAllowedOriginPatterns("*"); } /** * 客户端建立连接调用此方法 * 主要作用校验用户令牌信息,如果无效token则不能建立连接 * @author wuzhenyong */ @Override public void configureClientInboundChannel(ChannelRegistration registration) { registration.interceptors(new ChannelInterceptor() { @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (null == accessor) { return null; } // 判断是否首次连接请求 if (!StompCommand.CONNECT.equals(accessor.getCommand())) { // 不是首次连接,已经成功登陆 return message; } // 处理租户 String tenant = accessor.getFirstNativeHeader(CommonConstants.TENANT_ID); if (CharSequenceUtil.isNotBlank(tenant)) { TenantContextHolder.setTenantId(Integer.parseInt(tenant)); } else { TenantContextHolder.setTenantId(CommonConstants.TENANT_ID_1); } // 验证令牌信息 String token = accessor.getFirstNativeHeader("Authorization"); log.info("webSocket token is {}", token); if (null == token || token.length() <= 0) { return null; } /** * 以下是自定义用户令牌校验 */ OAuth2Authentication auth2Authentication = tokenService.loadAuthentication(token.split(" ")[1]); if (ObjectUtil.isNotNull(auth2Authentication)) { SecurityContextHolder.getContext().setAuthentication(auth2Authentication); accessor.setUser(auth2Authentication::getName); return message; } return null; } }); } }
服务端发送消息
// 注入,SimpMessagingTemplate 类来让开发者更加灵活地发送消息 @Autowired private SimpMessagingTemplate simpMessagingTemplate; // 发送消息代码 simpMessagingTemplate.convertAndSend("/test/2/1", content); // 说明:convertAndSend(自定义通道,发送内容) // 常用于:/发送消息前缀/用户ID/消息类型
VUE 依赖
// package.json文件 dependencies 属性下添加,然后执行npm install "sockjs-client": "1.0.0", "stomp-websocket": "2.3.4-next",
VUE代码
// 初始化 initWebSocket() { this.connection() const self = this // 断开重连机制,尝试发送消息,捕获异常发生时重连 this.timer = setInterval(() => { try { self.stompClient.send('test') } catch (err) { console.log('断线了: ' + err) self.connection() } }, 5000) }, // 连接 connection() { // 传入header信息 const token = store.getters.access_token const TENANT_ID = getStore({name: 'tenantId'}) ? getStore({name: 'tenantId'}) : '1' const headers = { 'TENANT-ID': TENANT_ID, 'Authorization': 'Bearer ' + token } // 建立连接对象 最后面的ws是我们定义的socketjs协议端点 this.socket = new SockJS('ws://127.0.0.1:8080/ws')// 连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息 // 获取STOMP子协议的客户端对象 this.stompClient = Stomp.over(this.socket) this.stompClient.debug = null // 向服务器发起websocket连接 this.stompClient.connect(headers, () => { // 订阅通道 /test/2/1 是与服务器发送消息的通道 定义好的哦 let target = `/test/2/1` this.stompClient.subscribe(target, (msg) => { // 订阅服务端提供的某个topic; this.$notify({ title: '提醒', type: 'warning', dangerouslyUseHTMLString: true, message: msg.body + '任务,请及时处理', offset: 60 }) }) }, (err) => { console.log(err) }) }, // 关闭连接 disconnect() { if (this.stompClient != null) { this.stompClient.disconnect() console.log('Disconnected') } }
以上发送消息的功能就完成啦,对于此聊天方式,服务端就一个配置类就可以进行聊天了哦。
关于前端连接websocket ,后台使用网关如何解决问题
在网关配置ws协议,然后前端进行连接的时候直接填写网关配置信息+/ws(/ws就是服务端创建的端点),也就是http协议也可以连接哦