springboot - angular -webSocket整合(主要用于实现)

参考文章:https://blog.csdn.net/zt15732625878/article/details/80560088

小菜鸟一枚,可能有很多问题,但功能已经简单实现

angular整合websocket

1、引入依赖

//依赖库
npm install ws --save  
//类型定义文件 
npm install @types/ws -save  

2、ts文件

import { Component, OnInit } from '@angular/core';
import {HttpClient, HttpHeaders} from '@angular/common/http';


@Component({
  selector: 'app-batch-task',
  templateUrl: './batch-task.component.html',
  styleUrls: ['./batch-task.component.css']
})


export class BatchTaskComponent implements OnInit {
  ws: WebSocket;//定义websocket
  constructor(private http: HttpClient) { }

  ngOnInit(): void {
  //打开页面时连接websocket
    this.openSocket()

  }

  //启动webSocket方法
   openSocket() {
   //判断浏览器支不支持
    if(typeof(WebSocket) == "undefined") {
      console.log("您的浏览器不支持WebSocket");
    }else{
      console.log("您的浏览器支持WebSocket");

    // 访问的后端地址 对应WebSocketServer.java的@ServerEndpoint("/imserver/{token}")
    //我这里使用的参数的token 大家可以自行设置
      var socketUrl="http://localhost:4433/imserver/"+$('#token')[0].innerHTML;
      //将http和https替换成ws  因为使用的是websocket协议
      socketUrl=socketUrl.replace("https","ws").replace("http","ws");
      console.log(socketUrl);
      //如果存在则关闭,然后重启
      if(this.ws!=null){
        this.ws.close();
        this.ws=null;
      }
      //实例化websocket
      this.ws = new WebSocket(socketUrl);

      //打开事件:这个主要是用来打开之后输出信息,同时也可以用send()发送信息给服务端
      this.ws.onopen = function() {
        console.log("websocket已打开");
        this.send("hi服务器,我开启了");
      };

      //获得消息事件:这里主要是处理后端sendText方法传过来的数据的处理,传回来的结果为msg
      this.ws.onmessage = function(msg) {
        console.log(msg.data);
      };

      //关闭事件
      this.ws.onclose = function() {
        console.log("websocket已关闭");
      };

      //发生了错误事件
      this.ws.onerror = function() {
        console.log("websocket发生了错误");
      }
    }
  }

  //发送消息方法为: this.send("信息")

}

如此一来,angular就处理好了,之后就整合后端

springboot整合websocket

1、导入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
            <scope>compile</scope>
        </dependency>

2、配置文件:主要是用来支持websocket

package com.fusdom.webSocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * 开启WebSocket支持
 * @author zhengkai
 */

//@Configuration注解
@Configuration
public class WebSocketConfig {

    //@Bean注解
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

3、!!! 对接口不能进行拦截

大家的拦截器有很多不同的用法,我们是在application.properties进行处理的,大家可以找个自己处理拦截的地方,不然访问接口时会给拦截
在这里插入图片描述
在这里插入图片描述
然后拦截的问题要怎么处理?? 这个我是在成功访问之后在WebSocketServer.java种的onOpen方法处理

4、WebSocketServer.java

这个方法类似于我们的controller 层,主要用于与前端之间的交互

package com.fusdom.webSocket;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fusdom.config.JWTConfig;
import com.fusdom.entity.TempInfo;
import com.fusdom.utils.DruidUtils;
import com.rabbitmq.client.Channel;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang.StringUtils;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * WebSocketServer:相当于ws协议的controller
 */

//这个地址类似我们requestMapping,前端可以通过这个地址进行访问
@ServerEndpoint("/imserver/{token}")
@Component
public class WebSocketServer {

    //日志
    static Log log= LogFactory.get(WebSocketServer.class);
    /**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;

    /**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
    //新建一个ConcurrentHashMap webSocketMap 用于接收当前userId的WebSocket,方便IM之间对userId进行推送消息。
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
    private Session session;
//    /**接收userId*/
    private String userId="";

//这个temp主要是用来处理mq发送数据的一些问题,后面我会贴上代码,可以看一下
    public static Session temp;

    /**
     * 连接建立成功调用的方法
	 */
    @OnOpen
    public void onOpen(Session session, @PathParam("token") String token) {

//这里是我的token处理,可以看着处理
        //去掉token前缀
        String afterToken = token.replace(JWTConfig.tokenPrefix, "");
        //解析JWT
        Claims claims = Jwts.parser()
                //设置解析秘钥
                .setSigningKey(JWTConfig.secret)
                //解析token
                .parseClaimsJws(afterToken)
                .getBody();

//如果有token的话,执行下面的逻辑,这里也就是你们要处理的
        if(claims!=null){
            //获取到session和userId
            this.session = session;
            this.userId= claims.getId().toString();
            this.temp=session;
            //如果userId存在,则移除,再添加一个相同的userId和新的Session(防止session过期)
            if(webSocketMap.containsKey(userId)){
                webSocketMap.remove(userId);
                webSocketMap.put(userId,this);
                //加入set中
            }else{
                webSocketMap.put(userId,this);
                //加入set中
                addOnlineCount();
                //在线数加1

            }

            log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());

            try {
                sendMessage(this.userId+"连接成功");


            } catch (IOException e) {
                log.error("用户:"+userId+",网络异常!!!!!!");
            }
        }else{
            log.error("用户:"+userId+",没有权限!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        //如果存在userId则移除,然后人数-1
        if(webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户退出:"+userId+",当前在线人数为:" + getOnlineCount());
    }


    /**
     * 收到客户端消息后调用的方法
     *@OnMessage可以用来接到客户端的信息之后的处理,可以在自己的方法上添加@OnMessage
     * @param message 客户端发送过来的消息*/
     
    @OnMessage
    public void onMessage(String message, Session session) {

	}

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送:主要是这个方法,拿到session之后发送想要的消息给前端
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

  

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
    public void setSession(Session session) {
        this.session = session;
    }


}

mq处理

这里的代码只供参考,没有太大的价值,只是想展示一下我怎么样调用WebSocketServer.java的sendMessage方法,这里也是为什么使用到temp的原因
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WalkerShen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值