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

后端代码

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 
 * 

* 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("订阅失败")
            
          }
        );
     

java中集成sockjs、stomp前端pc(vue)、h5和微信小程序连接_第1张图片
这样pc端就连接成功了

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

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

java中集成sockjs、stomp前端pc(vue)、h5和微信小程序连接_第2张图片
找个地方放起来

java中集成sockjs、stomp前端pc(vue)、h5和微信小程序连接_第3张图片
之后在页面上引用

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转换成微信小程序代码

java中集成sockjs、stomp前端pc(vue)、h5和微信小程序连接_第4张图片

你可能感兴趣的:(java,uni-app,vue,java,前端,微信小程序,vue,uni-app)