SpringBoot VUE WebSocket
前言
此文章基于服务端对客户端发送消息教程
采用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协议也可以连接哦