StudiousTiger 2022-03-20 20:27 采纳率: 50%
浏览 182
已结题

【报NullPointerException】springboot 中 websocket 的 @OnMessage 中使用自定义的工具类,报空指针异常

问题遇到的现象和发生背景

使用websocket谢了一个简单的聊天室,当聊天用户未上线的时候,给该未上线的用户发送消息,我是想保存将未上线用户为收到的消息保存到redis中,以便该未登录用户下次登录后可以从redis中获取其未登录是本应收到的消息。因为用户发送的消息是在onMessge中发送的,我在onMessage中使用自定义的RedisUtils(通过@Component注入到了springboot中了,用的时候使用了@Autowired自动装配),总是报“NullPointerException”。

问题相关代码,请勿粘贴截图
   @Autowired
    private RedisUtils redisUtil;

    // static:因为这个类是所有用户共享的,使用 static 可以保证存储的数据不会被覆盖
    private static Map<String,ChatEndpoint> onlineUser = new ConcurrentHashMap<>();

    // 声明 websocket session对象,使得每一个用户拥有自己的独立的 session,因此我们不能使用 static
    private Session wsSession;

    // 用户取出当前用户存在 httpSession 中的信息
    private HttpSession httpSession;

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig){
        try {
            // 给当前的 WebSocket Session 赋值
            this.wsSession = session;
            // 获取 httpSession,并存入当前的 httpSession
            this.httpSession = (HttpSession) endpointConfig.getUserProperties().get(HttpSession.class.getName());

            onlineUser.put((String) httpSession.getAttribute("userId"), this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

@OnMessage
    public void onMessage(String message, Session session){
        try {
            // 将JSON 转换成 Object
            MyMessage myMessage = JSON.parseObject(message, MyMessage.class);

            // 获取要发送的消息(JSON)
            String targetSendMessage = MessageUtils.getMessage(false,(String) httpSession.getAttribute("userId"), myMessage.getMessage());

            String listID = myMessage.getToName() + httpSession.getAttribute("userId");

            // 获取当前在线的用户集合
            Set<String> onlineUsers = onlineUser.keySet();
            // 若发送消息的目标在线,直接发送消息
            if (onlineUsers.contains(myMessage.getToName())) {
                // 发送消息
                onlineUser.get(myMessage.getToName())    // 获取目标用户对应的 ChatEndpoint 类
                        .wsSession   // 目标用户对应的 ChatEndpoint 类的成员变量
                        .getBasicRemote()  //
                        .sendText(targetSendMessage);  // 发送消息(targetSendMessage  : JSON)

            } else { // 发送消息的目标不在线
                // 获取以目标用户为主角的我们的聊天记录
                List<Object> chatRecordOfText = getChatRecordOfText(listID);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private List<Object> getChatRecordOfText(String listID){
        try {
            return redisUtil.lGet(listID+"chattxt", 0, -1);
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }
运行结果及报错内容

img

img

我的解答思路和尝试过的方法

1、我试过 new RedisUtils(),结果也是“空指针异常”

我想要达到的结果

能够在 OnMessage 使用自定义个 RedisUtils 访问 redis 服务器

  • 写回答

1条回答 默认 最新

  • StudiousTiger 2022-03-20 23:01
    关注

    ###解决了,我之前不知道为什么 @Autowried会失败,最后我使用手动注入RedisUtils,成功了。

    将原本的自动注入:

    @Autowired
        private RedisUtils redisUtil
    

    改为手动注入:

    private RedisUtils redisUtil = BeanUtils.getBean(RedisUtils.class);
    

    Bean工具类:

    @Component
    public class BeanUtils implements ApplicationContextAware  {
        protected static ApplicationContext applicationContext ;
    
        @Override
        public void setApplicationContext(ApplicationContext arg0) throws BeansException {
            if (applicationContext == null) {
                applicationContext = arg0;
            }
     
        }
        /**
         * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象
         */
        public static <T> T getBean(Class<T> clazz) {
            return applicationContext.getBean(clazz);
        }
    }
    

    完美解决

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 3月28日
  • 已采纳回答 3月20日
  • 创建了问题 3月20日

悬赏问题

  • ¥20 数据结构—复杂度分析
  • ¥15 如何使用单链表编写学生信息管理系统?
  • ¥15 完成课题以及ppt 在21号之前完成
  • ¥15 懂的来,你应该知道我在说什么,我需要你的帮助
  • ¥15 关于#java#的问题,请各位专家解答!
  • ¥15 maccms影视模板 制作影视网站失败 求
  • ¥15 stm32按键设置闹钟数进退位不正常
  • ¥15 自己写的测试驱动程序无法启动
  • ¥15 三电平逆变器中点电位平衡问题
  • ¥20 这怎么写啊 java课设