springoot项目 使用webSocket统计在线人数时,无法注入其他bean

今天让写一个简单的webSocket ,以便于达到统计在线人数
1.导入jar

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

2.webSocket 配置类

@Configuration
public class WebSocketConfig{
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3.webSocket服务端

package com.ht.cps.service;

import com.alibaba.fastjson.JSONObject;
import com.ht.cps.common.constantInterface.ConstantStatus;
import com.ht.cps.common.utils.RabbitAdminUtils;
import com.ht.cps.entity.india.HtIndiaMemberInfo;
import com.ht.cps.entity.india.MemberOnlineCountMsg;
import com.ht.springboot.snake.utils.FastJsonUtils;
import com.ht.springboot.snake.utils.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
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.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Description ContentWebSocket
 * @Author not a good person
 * @Date 2020/7/27 12:20
 */
@ServerEndpoint("/websocket/{sid}")//该注解表示该类被声明为一个webSocket终端
@Component
@Slf4j
public class WebSocketServer {

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    private final static Set<String> set =new HashSet<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //接收sid
    private String sid="";

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private RabbitAdminUtils rabbitAdminUtils;
    
   


    /**
     * 连接建立成功调用的方法
     * @param session
     * @param sid
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) throws IOException {
        log.info("有一连接开启  :" + sid);
        this.session = session;
        webSocketSet.add(this);     //加入set中
        if (!set.contains(sid)){
            set.add(sid);
            HtIndiaMemberInfo info = this.getOoIdAndMemberId(sid);
            if (ValidationUtil.isNotBlank(info)){
                try {
                    this.setParam(1,info.getMemberId(),info.getOoId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info(info.getOoId()+" 机构下的 userId : " + info.getMemberId()+" 用户上线");
            }
        }
        this.sid=sid;
        sendMessage("连接成功");

    }

    public HtIndiaMemberInfo getOoIdAndMemberId(String str) {
        String userKey = ConstantStatus.MEMBER_INFORMATION + str;
        String s = redisTemplate.opsForValue().get(userKey);
        if (ValidationUtil.isNotBlank(s)){
            JSONObject jsonObject = FastJsonUtils.parseObject(s);
            String ooId = jsonObject.getString("ooId");
            Integer memberId = jsonObject.getInteger("memberId");
            return new HtIndiaMemberInfo(ooId, memberId);
        }else {
            return null;
        }


    }
    public void setParam(Integer type,Integer userId,String ooId)throws Exception{
        MemberOnlineCountMsg msg = new MemberOnlineCountMsg();
        msg.setStatus(type);
        msg.setMemberId(userId);
        msg.setOoId(ooId);
        this.send(msg);
    }

    public void send(MemberOnlineCountMsg msg) throws Exception{
        try {
            rabbitAdminUtils.sendMessageForFanout("membercount", null,FastJsonUtils.toJSONString(msg));
        } catch (Exception e) {
            log.error("rabbitAdminUtils 发送消息失败");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        String sid = this.sid;
        log.info("有一连接关闭  :" + sid);
        if (set.contains(sid)){
            set.remove(sid);
            HtIndiaMemberInfo info = this.getOoIdAndMemberId(sid);
            if (ValidationUtil.isNotBlank(info)){
                try {
                    this.setParam(2,info.getMemberId(),info.getOoId());
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
                log.info(info.getOoId()+" 机构下的 userId : " + info.getMemberId()+" 用户下线");
            }
        }
    }


    /**
     * 接收客户端发送过来的消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自窗口" + sid + "的信息:" + message);
        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }


    /**
     * 实现服务器主动推送
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 群发自定义消息
     * @param message
     * @param sid
     * @throws IOException
     */
    public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
        log.info("推送消息到窗口"+sid+",推送内容:"+message);
        for (WebSocketServer item : webSocketSet) {
            try {
                //这里可以设定只推送给这个sid的,为null则全部推送
                if(sid==null) {
                    item.sendMessage(message);
                }else if(item.sid.equals(sid)){
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
    public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
        return webSocketSet;
    }

}

接过这个样子,redisTemplate 和RabbitAdminUtils 这2个bean都是无法注入的,然后就开始百度找攻略。。。

4.先写一个上下文工具类SpringUtils

package com.ht.cps.common.utils;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Repository;

/**
 * @Description SpringUtils
 * @Author not a good person
 * @Date 2020/7/29 17:11
 */
@Repository
public class SpringUtils implements BeanFactoryPostProcessor {

    //Spring应用上下文环境
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    public static ConfigurableListableBeanFactory getBeanFactory() {
        return beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws org.springframework.beans.BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) getBeanFactory().getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws org.springframework.beans.BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) getBeanFactory().getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return getBeanFactory().containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getAliases(name);
    }
}

5.更改websocket注入bean的获取方式如下

package com.ht.cps.service;

import com.alibaba.fastjson.JSONObject;
import com.ht.cps.common.constantInterface.ConstantStatus;
import com.ht.cps.common.utils.RabbitAdminUtils;
import com.ht.cps.common.utils.SpringUtils;
import com.ht.cps.entity.india.HtIndiaMemberInfo;
import com.ht.cps.entity.india.MemberOnlineCountMsg;
import com.ht.springboot.snake.utils.FastJsonUtils;
import com.ht.springboot.snake.utils.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
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.HashSet;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Description ContentWebSocket
 * @Author not a good person
 * @Date 2020/7/27 12:20
 */
@ServerEndpoint("/websocket/{sid}")//该注解表示该类被声明为一个webSocket终端
@Component
@Slf4j
public class WebSocketServer {

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    private final static Set<String> set =new HashSet<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //接收sid
    private String sid="";

    private StringRedisTemplate stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);

    private static RabbitAdminUtils rabbitAdminUtils = SpringUtils.getBean(RabbitAdminUtils.class);


    /**
     * 连接建立成功调用的方法
     * @param session
     * @param sid
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) throws IOException {
        log.info("有一连接开启  :" + sid);
        this.session = session;
        webSocketSet.add(this);     //加入set中
        if (!set.contains(sid)){
            set.add(sid);
            HtIndiaMemberInfo info = this.getOoIdAndMemberId(sid);
            if (ValidationUtil.isNotBlank(info)){
                try {
                    this.setParam(1,info.getMemberId(),info.getOoId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
                log.info(info.getOoId()+" 机构下的 userId : " + info.getMemberId()+" 用户上线");
            }
        }
        this.sid=sid;
        sendMessage("连接成功");

    }

    public HtIndiaMemberInfo getOoIdAndMemberId(String str) {
        String userKey = ConstantStatus.MEMBER_INFORMATION + str;
        String s = stringRedisTemplate.opsForValue().get(userKey);
        if (ValidationUtil.isNotBlank(s)){
            JSONObject jsonObject = FastJsonUtils.parseObject(s);
            String ooId = jsonObject.getString("ooId");
            Integer memberId = jsonObject.getInteger("memberId");
            return new HtIndiaMemberInfo(ooId, memberId);
        }else {
            return null;
        }


    }
    public void setParam(Integer type,Integer userId,String ooId)throws Exception{
        MemberOnlineCountMsg msg = new MemberOnlineCountMsg();
        msg.setStatus(type);
        msg.setMemberId(userId);
        msg.setOoId(ooId);
        this.send(msg);
    }

    public void send(MemberOnlineCountMsg msg) throws Exception{
        try {
            rabbitAdminUtils.sendMessageForFanout("membercount", null,FastJsonUtils.toJSONString(msg));
        } catch (Exception e) {
            log.error("rabbitAdminUtils 发送消息失败");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        String sid = this.sid;
        log.info("有一连接关闭  :" + sid);
        if (set.contains(sid)){
            set.remove(sid);
            HtIndiaMemberInfo info = this.getOoIdAndMemberId(sid);
            if (ValidationUtil.isNotBlank(info)){
                try {
                    this.setParam(2,info.getMemberId(),info.getOoId());
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
                log.info(info.getOoId()+" 机构下的 userId : " + info.getMemberId()+" 用户下线");
            }
        }
    }


    /**
     * 接收客户端发送过来的消息
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到来自窗口" + sid + "的信息:" + message);
        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /**
     * 群发自定义消息
     * @param message
     * @param sid
     * @throws IOException
     */
    public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
        log.info("推送消息到窗口"+sid+",推送内容:"+message);
        for (WebSocketServer item : webSocketSet) {
            try {
                //这里可以设定只推送给这个sid的,为null则全部推送
                if(sid==null) {
                    item.sendMessage(message);
                }else if(item.sid.equals(sid)){
                    item.sendMessage(message);
                }
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
    public static CopyOnWriteArraySet<WebSocketServer> getWebSocketSet() {
        return webSocketSet;
    }

}

最终问题解决,达到我了预期的效果这里还是非常感谢其他博主,这里贴上他的原文

https://blog.csdn.net/qq_21082615/article/details/91373094?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值