WebScoket 订阅与广播模式

版权声明:转载请取得博主同意 https://blog.csdn.net/weixin_43050247/article/details/89682675

1.maven依赖

<dependency>
  	<groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.configure配置

package com.myself.computerThinking.Subscription;

import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Component
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        /**
         * 用户可以订阅来自“/topic,/user”为前缀的消息
         * 客户端只可以订阅这个前缀的主题
         */
        registry.enableSimpleBroker("/topic","/user");

        /**
         * 客户端发送过来的消息,需要以“/app”为前缀,再通过Broker转发给响应的Controller
         */
        registry.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        /**
         * 路径:"websocket/socketServer.action"被注册为STOMP端点,对外暴露,客户端通过该路径接入webScoket服务
         */
       registry.addEndpoint("websocket/socketServer.action")
       .setAllowedOrigins("*")  //设置可以跨域请求
       .withSockJS();           // 添加SockJS支持    
    }
}

withSockJS() :添加SockJS的支持。(SockJS有关信息:https://blog.csdn.net/john_62/article/details/78208177)
SockJS是一个浏览器JavaScript库,它提供了一个类似于网络的对象。SockJS提供了一个连贯的、跨浏览器的Javascript API,它在浏览器和web服务器之间创建了一个低延迟、全双工、跨域通信通道。按浏览器是否支持WebSocket,以此使用三类传输对象:WebSocket > HTTP流 > HTTP长轮询

  • 如果添加了SockJS()支持,前段页面代码:var socket = new SockJS(url); url为http、https开头
  • 没有添加支持,var socket = new WebSocket(url); url为ws、wss开头

添加路径拦截器

	@Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler").withSockJS();
    }

    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }

3.spring boot静态资源

package com.myself.computerThinking.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        super.addResourceHandlers(registry);
    }
}

4.Controller&Server

@Controller
public class subController {

    @RequestMapping(value = "/stomp")
    public String getStopm(){
        return "stomp";
    }
    /**
     *   接收前端发送消息: stompClient.send("/app/welcome", {atytopic:"greetings"}, "123");
     *   并广播出去,广播地址为:/topic/CCC
     * @param message
     * @param topic
     * @param headers
     * @return
     */
    @MessageMapping("/welcome")
    @SendTo("/topic/CCC")
    public String sendMessage(String message, @Header("atytopic")String topic, @Headers Map<String,Object> headers) {
        System.out.println(topic);
        System.out.println(headers);
        System.out.println(message);
        return message;
    }
}
package com.myself.computerThinking.Subscription;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TaskServiceImpl implements TaskService {

    private final static Logger logger= LoggerFactory.getLogger(TaskServiceImpl.class);
   
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

@Scheduled(cron="0/10 * *  * * ? ")   //CRON表达式每10秒执行一次
    @Override
    public void selectCurDayDepotOrderInfo() {
        logger.info("=====================AAA频道每10秒执行一次刷新=====================");
        simpMessagingTemplate.convertAndSend("/topic/AAA","123");
    }

 @Scheduled(cron="0/13 * *  * * ? ")
    @Override
    public void selectCustomerOrderInfo() {
        logger.info("=====================BBB频道每13秒执行一次刷新=====================");
        simpMessagingTemplate.convertAndSend("/topic/AAA", "456");
    }
}
  • 使用@Scheduled,需要开启计时注解 @enablescheduling
  • @MessageMapping("/welcome") 接受前端传递 send的值,该页面要有@controller注释
  • @SendTo("/topic/CCC") 发送消息给订阅了CCC主题的前端
  • @SendTo 与 @SendToUser 是Spring的STOMP协议中注解的标签。
    @SendTo会将接收到的消息发送到指定的路由目的地,所有订阅该消息的用户都能收到,属于广播。
    @SendToUser消息目的地有UserDestinationMessageHandler来处理,会将消息路由到发送者对应的目的地。默认该注解前缀为/user。如:用户订阅/user/hi ,在@SendToUser(’/hi’)查找目的地时,会将目的地的转化为/user/{name}/hi, 这个name就是principal的name值,该操作是认为用户登录并且授权认证,使用principal的name作为目的地标识。发给消息来源的那个用户。(就是谁请求给谁,不会发给所有用户,区分就是依照principal-name来区分的)。
    此外该注解还有个broadcast属性,表明是否广播。就是当有同一个用户登录多个session时,是否都能收到。取值true/false.

5.前端代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>接受消息</title>
</head>
<body>

</body>

<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/sockjs.min.js"></script>
<script src="/static/js/stomp.js"></script>

<script th:inline="javascript">
    var url=getUrl();
    console.log(url);
    var  socket = new SockJS(url);   //WebSocket对应的地址
    stompClient = Stomp.over(socket);
    var headers={
        username:'admin',
        password:'admin'
    };
    stompClient.connect(headers, function (frame) {
        console.log('Connected: ' + frame);
        //订阅AAA频道
        stompClient.subscribe('/topic/AAA', function (greeting) {
            //后台传过来的json字符串转换为json对象
            console.log("AAA"+greeting);
        });
        //订阅BBB频道
        stompClient.subscribe('/topic/BBB', function (greeting) {
            //后台传过来的json字符串转换为json对象
            console.log("BBB"+greeting);
            //处理并显示数据
        });
        //订阅BBB频道
        stompClient.subscribe('/topic/CCC', function (greeting) {
            //后台传过来的json字符串转换为json对象
            console.log("CCC"+greeting);
            //处理并显示数据
        });
    });

    //获取项目路径
    function getUrl() {
        var strFullPath=window.document.location.href;
        var strPath=window.document.location.pathname;
        var pos=strFullPath.indexOf(strPath);
        var prePath=strFullPath.substring(0,pos);
        var postPath=strPath.substring(0,strPath.substr(1).indexOf('/')+1);
        var basePath = prePath+postPath;
        var url=basePath+"//websocket/socketServer.action";
        return url
    }
</script>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_43050247/article/details/89682675