最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

来源:博客园

SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

参考:

1、https://www.mchweb.net/index.php/dev/887.html


(相关资料图)

2、https://itonline.blog.csdn.net/article/details/81221103?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-81221103-blog-121078449.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-81221103-blog-121078449.pc_relevant_aa&utm_relevant_index=1

3、https://blog.csdn.net/yingxiake/article/details/51224569

使用场景

广播模式:使用场景:给所有连接了这个通道的客户端发送消息。

  • convertAndSend()
  • @SendTo

点对点模式:使用场景:单独给当前用户发送消息。

  • 下面两种方式,都默认加了一个前缀:/user

  • convertAndSendToUser()

  • @SendToUser

一、后端SpringBoot + WebSocket基础配置

1、导包

org.springframework.bootspring-boot-starter-websocket

2、配置config

  • 细节:必须配置跨域。低版本的SpringBoot(2.1.5.RELEASE 就不行)不行,需要使用高版本。低版本的解决方案还未找到。
  • 跨域配置使用:.setAllowedOriginPatterns("*")。。不能使用:.setAllowedOrigins("*")
package com.cc.ws.config;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;/** * 

@EnableWebSocketMessageBroker 的作用

*
  • 注解开启使用STOMP协议来传输基于代理(message broker)的消息,
  • *
  • 这时控制器支持使用 @MessageMapping,就像使用 @RequestMapping一样
  • * @author cc * */@Configuration@EnableWebSocketMessageBrokerpublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer { /**

    启动简单Broker

    *

    表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息

    *

    代理的名字:都是自定义的

    * * /user 点对点(默认也是/user,可以自定义,但是必须和setUserDestinationPrefix中的设置一致) * /topic1 广播模式1 * /topic2 广播模式2 * * /mass 广播模式:群发 */ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker( "/user", "/topic1", "/topic2", "/mass" ); // 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是 /user/ // 注意,这里必须和上面设置的Broker:/user 一致(两个都可以自定义,但必须一致)。否则连接不上 registry.setUserDestinationPrefix("/user/"); // 指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀// registry.setApplicationDestinationPrefixes("/socket"); } /** * 这个方法的作用是添加一个服务端点,来接收客户端的连接。 * registry.addEndpoint("/socket")表示添加了一个/socket端点,客户端(前端)就可以通过这个端点来进行连接。 * withSockJS()的作用是开启SockJS支持。 * @param registry registry */ @Override public void registerStompEndpoints(StompEndpointRegistry registry) { // 注册一个STOMP的endpoint端点,并指定使用SockJS协议 // 前端使用这个地址连接后端 WebSocket接口 registry.addEndpoint("/broadcast", "/point") // 允许所有源跨域。还可以指定ip配置:http://ip:* // 低版本的SpringBoot(2.1.5.RELEASE 就不行)不行 .setAllowedOriginPatterns("*") .withSockJS(); }}

    3、启动类,配置定时器

    • @EnableScheduling
    @SpringBootApplication@EnableSchedulingpublic class WebSocketDemoApplication {    public static void main(String[] args) {        SpringApplication.run(WebSocketDemoApplication.class, args);    }}

    二、前端基础配置

    let socket1 = new SockJS("http://服务器ip:服务器端口/broadcast");       let stompClient1 = Stomp.over(socket1);//广播模式    stompClient1.connect({}, (frame) => {      stompClient1.subscribe("/topic1/", (message) => {        console.log(message.body);      });    });

    三、后端不接收,只发送

    • 使用spring Scheduled 定时发送消息

    • 直接使用:SimpMessagingTemplate 的 convertAndSend广播模式 和 convertAndSendToUser点对点模式

    1、后端

    • 注意点对点发送:

    convertAndSendToUser的默认前缀(/user)是在WebSocketConfig配置文件中配置的。

    代码:

    @Resource    private SimpMessagingTemplate simpMsgTemp;    /** 广播推送消息1:会发送给所有连接了 topic1 这个通道的客户端。     * topic1:在Broker中配置     **/    @Scheduled(cron = "0/1 * * * * ?")    public void getSocket(){        String msg = String.format("%s 的第 %s 个消息", "topic1", LocalDateTime.now().getSecond());        log.info("{}",msg);        simpMsgTemp.convertAndSend("/topic1/", msg);    }    /** 广播推送消息2:多指定一个uri。相当于另一条通道(推荐使用)     * 
  • 自定义url后缀,还可以实现用户和用户单点发送。
  • * topic2:在Broker中配置 * custom:是自定义的 */ @Scheduled(cron = "0/1 * * * * ?") public void getSocketUser(){ String msg = String.format("topic2 的第 %s 个消息", LocalDateTime.now().getSecond()); log.info("{}",msg); simpMsgTemp.convertAndSend("/topic2/custom" ,msg); } /**点对点发送 convertAndSendToUser(第一个参数:一般是用户id) * -> 假如用户id是1。用用户id是1的在两个地方登陆了客户端(比如不同的浏览器登陆同一个用户), * -> convertAndSendToUser会把消息发送到用户1登陆的两个客户端中 * 发送到:/user/{userId}/cs 下。cs是自定义的,且必须自定义一个。 */ @Scheduled(cron = "0/1 * * * * ?") public void pointToPoint(){ //这个用户id是后端获取的当前登陆的用户id String userId = "123"; String msg = String.format("点对点:第 %s 个消息。用户id:%s", LocalDateTime.now().getSecond(), userId); log.info("{}",msg); //发送 simpMsgTemp.convertAndSendToUser(userId,"/cs/" ,msg); }

    2、前端

    • 注意点对点的接收方式,用户id需要取出前端存的用户id
    //这样才能同时接收后端来的三套不同通道的消息。    // broadcast 和后端:registerStompEndpoints中的配置必须一致    // point     和后端:registerStompEndpoints中的配置必须一致    // broadcast、point 也可以只用一个,这里只是为了好区分。    let socket1 = new SockJS("http://172.16.8.1:8099/broadcast");    let socket2 = new SockJS("http://172.16.8.1:8099/broadcast");    let socket3 = new SockJS("http://172.16.8.1:8099/point");    // console.log("wb:" + socket)    let stompClient1 = Stomp.over(socket1);    let stompClient2 = Stomp.over(socket2);    let stompClient3 = Stomp.over(socket3);    // ----------------广播模式1--------------------    stompClient1.connect({}, (frame) => {      console.log("-----------frame1", frame)      stompClient1.subscribe("/topic1/", (message) => {        console.log(message.body);        this.msg = message.body;        // console.log(JSON.parse(message.body));      });    });    // ----------------广播模式2--------------------    stompClient2.connect({}, (frame) => {      console.log("-----------frame2", frame)      stompClient2.subscribe("/topic2/custom", (message) => {        console.log(message.body);        this.user = message.body;        // console.log(JSON.parse(message.body));      });    });    // ----------------点对点模式--------------------    //前端获取的 userId    let userId = "123";    //连接WebSocket服务端    stompClient3.connect({},(frame) => {      console.log("Connected:" + frame);      stompClient3.subscribe("/user/" + userId + "/cs/",          (response) => {            this.peer = response.body;      });    });

    四、后端接收、接收后再发送

    • 也可以只接收消息,不发送。看业务需求。
    • 使用 @MessageMapping接收前端发送过来的消息
    • 使用:@SendTo广播模式、@SendToUser点对点模式
    • 使用:SimpMessagingTemplate 的 convertAndSend广播模式 和 convertAndSendToUser点对点模式

    1、后端

    @Resource    private SimpMessagingTemplate simpMsgTemp;    /** 

    广播模式一、接收前端的消息,处理后给前端返回一个消息。

    *
  • 后端 把消息处理后 发送到 /mass/getResponse 路径下
  • *
      *
    1. @MessageMapping("/massRequest1") :作用:接收前端来的消息。类似于@RestController
    2. *
    3. @SendTo("/mass/getResponse1"):作用跟convertAndSend类似,广播发给与该通道相连的客户端。SendTo 发送至 Broker 下的指定订阅路径
    4. *
    5. @SendToUser("/mass/getResponse1"):作用跟convertAndSendToUser类似,定点发送。SendTo 发送至 Broker 下的指定订阅路径
    6. *
    7. /mass 必须在配置文件配置
    8. *
    9. /getResponse1 自定义的后缀
    10. *
    */ @MessageMapping("/massRequest1") @SendTo("/mass/getResponse1") public String mass1(String chatRoomRequest){ //处理前端消息…… log.info("前端消息:{}",chatRoomRequest); //返回消息 return "@SendTo 广播一(单次) 后端处理完成!"; } /** 广播模式二、接收前端的消息,可以多次给前端发消息 *
  • /mass 必须在配置文件配置
  • *
  • /getResponse2 自定义的后缀
  • */ @MessageMapping("/massRequest2") public void mass2(String chatRoomRequest){ log.info("前端的消息:{}",chatRoomRequest); for (int i = 0; i < 5; i++) { String msg = "后端处理后的 广播二(多次):" + i; simpMsgTemp.convertAndSend("/mass/getResponse2", msg); } simpMsgTemp.convertAndSend("/mass/getResponse2", "后端处理后的 广播二(多次),后端处理完成!"); } /**

    点对点一、接收前端消息,只能返回一次消息(必须登陆系统才能使用。)

    *
  • 只有发送原始消息的客户端才会收到响应消息,而不是所有连接的客户端都会收到响应消息。
  • *
  • /alone/getResponse1:自定义的,不需要在配置文件配置。
  • * *

    @SendToUser

    *
  • 默认该注解前缀为 /user
  • *
  • broadcast属性,表明是否广播。就是当有同一个用户登录多个session时,是否都能收到。取值true/false.
  • * * @param principal Principal :登陆用户的信息,需要使用spring s安全框架写入信息? */ @MessageMapping("/aloneRequest1") @SendToUser("/alone/getResponse1") public String alone1(String chatRoomRequest){ //处理前端消息…… log.info("前端消息:{}",chatRoomRequest); //返回消息 return "@SendToUser 点对点一(单次) 后端处理完成!"; } /** 点对点二、接收前端消息,可以多次给前端发消息 *
  • convertAndSendToUser —— 发送消息给指定用户id的
  • *
  • 如果用户1在两个地方(A/B)登陆可以客户端,并且连接了该通道,其中一个如A给后端发消息,后端返回消息,A/B两个地方都会收到消息
  • *
      *
    1. @MessageMapping("/aloneRequest2") 接收前端指定用户消息,
    2. *
    3. /alone/getResponse2 不用在配置文件中配置
    4. *
    5. 返回消息 发送到 user/{userId}/alone/getResponse2 下 (定点发送)
    6. *
    */ @MessageMapping("/aloneRequest2") public void alone2(String chatRoomRequest){ //后端获取的当前登陆的用户的id(和前端一致) String userId = "456"; log.info("前端的消息:{}",chatRoomRequest); for (int i = 0; i < 5; i++) { String msg = "后端处理后的 点对点二(多次):" + i; simpMsgTemp.convertAndSendToUser(userId,"/alone/getResponse2", msg); } simpMsgTemp.convertAndSendToUser(userId,"/alone/getResponse2", "后端处理后的 点对点二(多次),后端处理完成!"); }

    2、前端

    • 3点对点一 未实现。
    //连接SockJS的 broadcast    let socket1 = new SockJS("http://172.16.8.7:8099/broadcast");    let socket2 = new SockJS("http://172.16.8.7:8099/broadcast");    let socket3 = new SockJS("http://172.16.8.7:8099/point");    let socket4 = new SockJS("http://172.16.8.7:8099/point");    //使用STMOP子协议的WebSocket客户端    let stompClient1 = Stomp.over(socket1);    let stompClient2 = Stomp.over(socket2);    let stompClient3 = Stomp.over(socket3);    let stompClient4 = Stomp.over(socket4);    //1广播模式一    stompClient1.connect({},(frame) => {      console.log("广播模式一:" + frame);      //1发送消息      stompClient1.send("/massRequest1",{},"我是前端来 广播模式一 的消息!");      //2接收消息      stompClient1.subscribe("/mass/getResponse1",(response) => {        this.broadcast1 = response.body      });    });    //2广播模式二    stompClient2.connect({},(frame) => {      console.log("广播模式二:" + frame);      //1发送消息      stompClient2.send("/massRequest2",{},"我是前端来 广播模式二 的消息");      //2接收消息      stompClient2.subscribe("/mass/getResponse2",(response) => {        this.broadcast2 = response.body      });    });    //3点对点一 :必须登陆系统才能实现。要往:Principal设置用户登陆信息才行    //1发送消息    // stompClient3.send("/aloneRequest1",{},"我是前端来 点对点一 的消息");    stompClient3.connect({},(frame) => {      console.log("点对点一1:" + frame);      stompClient3.send("/aloneRequest1",{},"我是前端来 点对点一 的消息");      //2接收消息      stompClient3.subscribe("/user/alone/getResponse1" ,(response) => {        console.log("-------response.body", response.body)        this.point1 = response.body      });    });    //4点对点二:必须获取现在登陆了的用户id,且必须和后端一致才行。    stompClient4.connect({},(frame) => {      console.log("点对点二:" + frame);      //1发送消息      stompClient4.send("/aloneRequest2",{},"我是前端来 点对点二 的消息");      //2接收消息      //前端获取的当前登陆的用户userId(和后端一致)      let userId = "456";      stompClient4.subscribe("/user/"+userId+"/alone/getResponse2",(response) => {        this.point2 = response.body      });    });

    关键词: