上一篇已经写了一个传统方式的websocket实现,在浏览过程看到也有使用stomp 方式 所以很想尝试一下 代码里面有详细使用的说明
主要代码
后端代码
配置
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* @Author: lkz
* @Title: WebSocketBrokerConfig
* @Description: 另外一种方法
* //@EnableWebSocketMessageBroker注解表示开启使用STOMP协议来传输基于代理的消息,Broker就是代理的意思。
* @Date: 2022/10/14 9:42
* https://github.com/JustCoding-Hai/subtlechat-vue/wiki/3.%E4%BD%BF%E7%94%A8websocket%E5%AE%9E%E7%8E%B0%E7%BE%A4%E8%81%8A
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {
/**
* 配置消息代理,哪种路径的消息会进行代理处理
* configureMessageBroker方法用来配置消息代理,由于我们是实现推送功能,这里的消息代理是/topic
* 作用:1.消息代理会处理前缀为“/topic”的消息
* 2.客户端发送到服务端的消息需要带有“/app”前缀
* @param registry
* //在topic和user这两个域上服务端可以向客户端发消息 设置广播节点
* registry.enableSimpleBroker("/topic", "/user");
* //客户端向服务器端发送时的主题上面需要加"/app"作为前缀
* registry.setApplicationDestinationPrefixes("/app");
* //服务端给客户端指定用户发送一对一的主题,前缀是"/user"
* registry.setUserDestinationPrefix("/user");
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//服务端发送消息将消息传入带有topic开头订阅的客户端 ,
registry.enableSimpleBroker("/topic");
// 客户端发送消息时 ,需要以app作为前缀
registry.setApplicationDestinationPrefixes("/app"); //这个是客户端发消息时使用 ,作用不同于 registry.addEndpoint()
}
/**
* 作用:注册STOMP协议的节点(端点),并指定映射的URL。
* 将“/ws/websocket”注册为端点,客户端订阅消息或发送消息到目的地前要连接该端点
* 添加这个Endpoint,这样在网页中就可以通过websocket连接上服务,也就是我们配置websocket的服务地址,并且可以指定是否使用socketjs
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//注册STOMP协议节点,同时指定使用SockJS协议。
registry.addEndpoint("/wsWeb") // 确保客户端可以正常连接,同@ServerEndpoint("/ws")方式一样 如果有安全拦截 放行即可
.setAllowedOrigins("*") //处理跨域 单体需要打开 微服务如果在网关中配置了就不需要
.withSockJS();
}
/**
* 上面以ws的消息都会被路由到带有@MessageMapping
* 以topic的消息都会发送到STOMP代理中,给根据所选择的stomp代理不同,选择的前缀也有限制
* 以user开头的消息会将消息重路由到某个用户独有的目的地上
* 接收客户端发来的消息,参数就是消息本身message
* @MessageMapping 或者 @SubscribeMapping 注解可以处理客户端发送过来的消息,并选择方法是否有返回值。
* @MessageMapping 指定目的地是“/app/test”(“/app”前缀是隐含的,因为我们将其配置为应用的目的地前缀)。
* 通信协议可以自定义——可自定义参数的格式
* 可以接收json格式的数据,传递josn数据时不需要添加额外注解@Requestbody
* 消息发送者不是从前端传递过来的,而是从springsecurity中获取的,防止前端冒充
* 如果 @MessageMapping 注解的控制器方法有返回值的话,返回值会被发送到消息代理,只不过会添加上"/topic"前缀。
* 通过为方法添加@SendTo注解,重载目的地
*
* @MessageMapping 用在@Controller注解的类中,根据目的地路由消息的方法
*
* @SendTo 自定义要将有效内容发送到的目标,一般用于广播消息
*
* @SendToUser 是仅向与消息关联的用户发送消息
*
*/
}
控制层
@Controller
public class WebsocketController {
@Resource
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/test")
public void test(String message){
System.out.println("接收到客户端发送来的消息:"+message);
simpMessagingTemplate.convertAndSend("/topic/sub",message); // 前端订阅
}
}
后端控制台
前端代码
首先vue需要安装依赖 stomp js 和sockjs依赖 ,我感觉只要安装stomp依赖即可
npm install --save stompjs
在需要使用的地方导入
import SockJS from "sockjs-client";
import Stomp from "stompjs";
主要业务代码
myInfo(){
// this.initWebsocket();
this.initStompSocket();
},
//websocket 相关开始
// stomp方式
initStompSocket(){
//使用sockjs建立连接,并发起请求
var stompClients= Stomp.over(new SockJS("http://localhost:8603"+"/wsWeb",null,{timeout: 15000}));
this.stompClient=stompClients;
// 连接成功回调 参考请求头填 待测试 https://www.cnblogs.com/wwxdxgb/p/16261720.html
// const headers={
// Authorization: ""
// }
// 参考 方法 https://www.likecs.com/ask-2883310.html?sc=1800
stompClients.connect({},success=>{
//订阅服务端发送过来的消息 这里是广播
console.log("连接成功")
// 同下面的都可以发送,唯一不同的是 箭头函数指向当前对象,function,如果使用this指向的当前window ,调用下面的发送消息 会找不到方法 ,所以function函数的时候 我是用的是stompClients本身
//stompClients.subscribe("/topic/sub",function (msg) {
this.stompClient.subscribe("/topic/sub", msg=> {
console.log('成功订阅到消息:'+msg.body)
//同时发送一条消息给服务端
var token= getCookie("token");
var st="订阅成功后发送的数据";
// this.sendMsg(st) // 下面这两种方式都是往服务端发送消息 主要是测试使用 不然会一直发送消息,接收消息
//stompClients.send("/app/test",{},JSON.stringify(st))
});
//点对点 一般用于发送指定用户 ,可以自行百度
// this.stompClient.subscribe("/user",function (msg) {
// //this.stompClient.subscribe("/topic/sub", msg=> {
// console.log('成功订阅到消息:'+msg.body)
// //同时发送一条消息给服务端
// var token= getCookie("token");
// var st="订阅成功后发送的数据";
// // this.sendMsg(st)
// })
},fail=>{
console.log("建立连接失败")
//异常时重连
// if(this.stompCount>10){
// console.log("温馨提示: 您的连接已经断开,请重新登录")
// this.stompCount=0;
// }else{
// this.wsReconnect && clearTimeout(this.wsReconnect);
// this.wsReconnect = setTimeout(function () {
// console.log("开始重连...");
// this.initStompSocket();
// console.log("重连完毕...");
// this.stompCount++;
// }, 1000);
// }
this.stompClient.disconnect();
})
},
//这里是方便调用 发送的消息转换格式发送 确保后端能收到信息
sendMsg(data){
this.stompClient.send("/app/test",{},JSON.stringify(data))
},
控制台打印结果
参考的博客: https://blog.csdn.net/u013041642/article/details/108154230 https://fulongyuanjushi.blog.csdn.net/article/details/123970860 https://blog.csdn.net/qq_43581790/article/details/124791002
精彩链接
发表评论