java中集成sockjs、stomp前端pc(vue)、h5和微信小程序连接

4 篇文章 0 订阅
3 篇文章 0 订阅

后端代码

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
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 
 * <p>
 * WebSocket配置类
 */
@Slf4j
@Configuration
@AllArgsConstructor
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    private RemoteTokenServices tokenService;

    public static final String USER_DESTINATION_PREFIX = "/other/";


    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        log.info("WebSocket服务器注册");
        //配置两个入口,原因是因为小程序不支持sockjs
        registry.addEndpoint("/ws")
                .setAllowedOrigins("*")
                .withSockJS();
        registry.addEndpoint("/wsapp")
                .setAllowedOrigins("*");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        log.info("WebSocket服务器启动");
        //心跳检测
        ThreadPoolTaskScheduler tpts = new ThreadPoolTaskScheduler();
        tpts.setPoolSize(1);
        tpts.setThreadNamePrefix("wss-heartbeat-thread-");
        tpts.initialize();

        ///信息接收头
        registry.enableSimpleBroker("/topic", "/user").setHeartbeatValue(new long[]{10000,10000}).setTaskScheduler(tpts); ;
        //接收前缀
        registry.setApplicationDestinationPrefixes("/app");
        //请求前缀
        registry.setUserDestinationPrefix(USER_DESTINATION_PREFIX);
    }

    @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 (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    String tokens = accessor.getFirstNativeHeader("Authorization");
                    log.info("webSocket token is {}", tokens);
                    if (StrUtil.isBlank(tokens)) {
                        return null;
                    }
                    // 验证令牌信息
                    OAuth2Authentication auth2Authentication = tokenService.loadAuthentication(tokens.split(" ")[1]);
                    if (ObjectUtil.isNotNull(auth2Authentication)) {
                        SecurityContextHolder.getContext().setAuthentication(auth2Authentication);
                        accessor.setUser(() -> auth2Authentication.getName());
                        return message;
                    } else {
                        return null;
                    }
                }
                //不是首次连接,已经成功登陆
                return message;
            }
        });
    }
}
    @SubscribeMapping("/topic/pc")
    public R subPc() {
        return R.ok("订阅广播成功,当前时间:"+new Date());
    }

前端代码

vue连接
先npm sockjs-client和stompjs
之后在页面引用
import SockJS from ‘sockjs-client’;
import Stomp from ‘stompjs’;

connection() {
        let headers = {
           Authorization: 'Bearer ' + "4cf7d2df-f4a2-4295-b267-03dca1910459"
        };
        // 建立连接对象,这里配置了代理
        this.socket = new SockJS('/other/ws', null, {
          timeout: 10000
        }); //连接服务端提供的通信接口,连接以后才可以订阅广播消息和个人消息
        // 获取STOMP子协议的客户端对象
        this.stompClient = Stomp.over(this.socket);

        // 向服务器发起websocket连接
this.stompClient.connect(
          headers,
          () => {

            this.stompClient.subscribe('/app/topic/pc', function(greeting) {
              console.log(greeting, 668);
            });
          },
          err => {
            console.log("订阅失败")
            
          }
        );
     

在这里插入图片描述
这样pc端就连接成功了

之后使用uni-app生成h5和微信小程序

先npm sockjs-client和stompjs
之后去node——mode_modules把sockjs和stompjs都都复制出来

在这里插入图片描述
找个地方放起来

在这里插入图片描述
之后在页面上引用

import webScoket from '../../static/js/socket'
	let stompClient = ''
	import {
		Stomp
	} from '../../static/js/stomp.js';
	import 
		SockJS
	 from '../../static/js/sockjs.min.js';

生命周期,利用uni-app的选择编码对微信小程序和h5做区分

onShow() {
			// #ifdef MP-WEIXIN
		    const that = this
			var headers = {
				Authorization: 'Bearer ' + "4cf7d2df-f4a2-4295-b267-03dca1910459"
			};
		    Promise.all([webScoket.init(), webScoket.client()]).then(result => {
		      stompClient = result[1]
		      stompClient.connect(headers, () => {
		          stompClient.subscribe('/app/topic/pc', response => {
		            that.oj=response;
					console.log('收到订阅消息')
		            if (response.body) {
		              const res = JSON.parse(response.body)
		    
		              // 业务逻辑
		            }
		          })
		        })
		    })
			// #endif
		},
		
		onHide() {
			// #ifdef MP-WEIXIN
		    app.globalData.isReConnect = false
		    stompClient.disconnect()
			// #endif
		},
		
		onUnload() {
			// #ifdef MP-WEIXIN
		    app.globalData.isReConnect = false
		    stompClient.disconnect()
			// #endif
		},
		onLoad() {
			// #ifdef H5
			var info = uni.getSystemInfoSync();
			console.log('platform:: ' + info.platform);
			if (info.platform == 'other' && typeof window === 'object') {
				window.WebSocket = uni.webSocketBackup;
			}
			this.say();
			// #endif
		},
		say() {
			
			var that = this;
			var headers = {
				Authorization: 'Bearer ' + "4cf7d2df-f4a2-4295-b267-03dca1910459"
			};
			 var socket = new SockJS('http://10.10.10.110/other/ws');
			
			var stompClient = Stomp.over(socket);
    stompClient.connect(
      headers,
      () => {

        stompClient.subscribe('/app/topic/pc', function(greeting) {
          console.log(greeting, 668);
        });

      },
      err => {
		 
        console.log("订阅失败")
       

      }
    );
		},



socket.js

const appData = getApp()
const webScoket = {
  // 创建基于STOMP协议的WebSocket
  client: function () {
    const Stomp = require('./stomp.min.js').Stomp
    // setInterval是用来发心跳包的,而小程序没有window对象,所以要重新定义
    Stomp.setInterval = (interval, f) => {
      return setInterval(f, interval)
    }
    Stomp.clearInterval = (interval, f) => {
      return clearInterval(id)
    }
    return new Promise((resolve, reject) => {
      try {
        const stompClient = Stomp.over(appData.globalData.ws)
        resolve(stompClient)
      } catch (e) {
        reject(e)
      }
    })
  },
  // 初始化
  init: function (url = '') {
    // 增加全局webscoket配置
    appData.globalData.isConnected = false
    appData.globalData.isReConnect = true // 允许断线重连
    appData.globalData.reConnectLimit = -1 // 断线重连次数,-1不限次数
    appData.globalData.msgQueue = []
    appData.globalData.wsUrl = url || 'ws://10.10.10.110/other/wsapp'//这里对应ws地址(不带.withSockJS();的入口)
    appData.globalData.ws = {
      send: this.sendMsg,
      close: this.disConnect,
      onopen: null,
      onclose: null,
      onmessage: null
    }
    const that = this
    return new Promise((resolve, reject) => {
      //连接
      this.connect({
        success(msg) {
          that.onOpen() // 打开连接
          that.onMsg() //接收数据
          that.onError() //监听连接错误
          that.onClose() // 监听连接是否关闭
          resolve(msg)
        },
        fail(err) {
          reject(err)
        }
      })
    })
  },
  // 创建一个WebSocket连接,params:{url:'String',success:'successCallback',fail:'failCallback'}
  connect: function (params = {}) {
    console.log('connect')
    wx.connectSocket({
      url: appData.globalData.wsUrl,
	  header:{
	  	Authorization: 'Bearer ' + "4cf7d2df-f4a2-4295-b267-03dca1910459"
	  },
      success: (msg) => {
        if (params.hasOwnProperty('success')) {
          params.success(msg)
        }
      },
      fail: (err) => {
        if (params.hasOwnProperty('fail')) {
          params.fail(err)
        }
      }
    })
  },
  // 监听WebSocket连接打开事件
  onOpen: function () {
    console.log('onopen')
    wx.onSocketOpen((res) => {
      console.log('WebSocket连接已打开')
      appData.globalData.isConnected = true
      // 执行队列里未发送的任务
      appData.globalData.msgQueue.forEach(item => {
        this.sendMsg(item)
      })
      appData.globalData.msgQueue = []
      appData.globalData.ws.onopen && appData.globalData.ws.onopen()
    })
  },
  // 发送消息
  sendMsg: function (msg) {
    console.log('sendmsg')
    // 如果WebSocket已连接则发送消息
    if (appData.globalData.isConnected) {
      wx.sendSocketMessage({
        data: msg
      })
    } else {
      // WebSocket没有连接将消息放入队列中
      appData.globalData.msgQueue.push(msg)
    }
  },
  // 监听WebSocket接受到服务器的消息事件
  onMsg: function () {
    console.log('onmsg')
    wx.onSocketMessage((res) => {
      console.log('WebSocket收到消息事件:', res)
      appData.globalData.ws.onmessage && appData.globalData.ws.onmessage(res)
    })
  },
  // 监听WebSocket连接错误事件
  onError: (res) => {
    console.log('onerror')
    wx.onSocketError((res) => {
      console.log("WebSocket错误事件:", res)
    })
  },
  // 关闭WebSocket连接
  disConnect: function () {
    console.log('disconnect')
    wx.closeSocket()
  },
  // 监听WebSocket连接关闭事件
  onClose: function () {
    console.log('onclose')
    wx.onSocketClose((res) => {
      console.log('WebSocket连接关闭:', res)
      appData.globalData.ws.onclose && appData.globalData.ws.onclose(res)
      appData.globalData.isConnected = false
      // 断线重连
      if (appData.globalData.isReConnect) {
        // 调整重连的次数
        if (!appData.globalData.hasOwnProperty('reConnectLimit') || appData.globalData.reConnectLimit === 0) {
          appData.globalData.isReConnect = false
        } else {
          if (appData.globalData.reConnectLimit > 0) {
            appData.globalData.reConnectLimit--
          }
          console.log('剩余重连次数:', appData.globalData.reConnectLimit)
          this.connect({
            fail(err) {
              console.log('重新连接失败:', err)
            }
          })
        }
      }
    })
  }
}

export default webScoket

之后可以通过发行微信将uni-app转换成微信小程序代码

在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Vue 3, SockJS, and STOMP are all technologies commonly used in web development. Vue 3 is a JavaScript framework for building user interfaces, SockJS is a WebSocket emulation library, and STOMP (Simple Text Oriented Messaging Protocol) is a protocol used for real-time communication between clients and servers. In the context of Vue 3, you can use SockJS and STOMP to establish a WebSocket connection between your Vue application and a server. This allows for real-time data exchange between the client and the server. To use Vue 3 with SockJS and STOMP, you will need to install the necessary dependencies. You can do this using a package manager like npm or yarn. Here's an example of how you can install them: ```bash npm install sockjs-client stompjs ``` Once the dependencies are installed, you can import them in your Vue component and create a WebSocket connection. Here's a basic example: ```javascript import SockJS from 'sockjs-client'; import { Stomp } from '@stomp/stompjs'; export default { mounted() { const socket = new SockJS('http://your-server-url'); const client = Stomp.over(socket); client.connect({}, () => { // Connection successful client.subscribe('/topic/some-topic', (message) => { // Handle incoming messages console.log(message.body); }); }); }, }; ``` In this example, we create a new SockJS instance and establish a connection to the server URL specified. We then create a Stomp client over this socket and use the `connect()` method to establish a connection. Once the connection is established, we can subscribe to specific topics and handle incoming messages. This is just a basic example, and there are many other features and configurations you can explore with Vue 3, SockJS, and STOMP. I recommend referring to the official documentation of each library for more in-depth information and usage examples.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值