SpringBoot使用@ServerEndpoint無法@Autowired依賴注入問題解決


SpringBoot使用@ServerEndpoint無法@Autowired依賴注入問題解決

問題

websocket里面使用@Autowired注入service或bean時,報空指針異常。

@Component
@ServerEndpoint("/groupChat/{groupNo}/{uuid}")
public class GroupChatWebsocket {

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;
}

原因

spring管理的都是單例(singleton)和 websocket (多對象)相沖突。

需要了解一個事實:websocket 是多對象的,每個用戶的聊天客戶端對應 java 后台的一個 websocket 對象,前后台一對一(多對多)實時連接,
所以 websocket 不可能像 servlet 一樣做成單例的,讓所有聊天用戶連接到一個 websocket對象,這樣無法保存所有用戶的實時連接信息。
可能 spring 開發者考慮到這個問題,沒有讓 spring 創建管理 websocket ,而是由 java 原來的機制管理websocket ,所以用戶聊天時創建的
websocket 連接對象不是 spring 創建的,spring 也不會為不是他創建的對象進行依賴注入,所以如果不用static關鍵字,每個 websocket 對象的 service 都是 null。

原文鏈接

解決方案

  • 方法一 使用static靜態對象
private static RedisTemplateUtil redisUtil;
 
@Autowired
public static void setRedisTemplateUtil(RedisTemplateUtil redisUtil) {
	WebSocketServer.redisUtil = redisUtil;
}

  • 方法二 動態的從spring容器中取出RedisTemplateUtil 推薦方案
package cn.pconline.framework.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 獲取spring容器
 * 當一個類實現了這個接口ApplicationContextAware之后,這個類就可以方便獲得ApplicationContext中的所有bean。
 * 換句話說,這個類可以直接獲取spring配置文件中所有有引用到的bean對象
 * 前提條件需作為一個普通的bean在spring的配置文件中進行注冊 
 */
public class SpringCtxUtils implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    	SpringCtxUtils.applicationContext = applicationContext;
    }


    public static <T> T getBean(Class<T> type) {
        try {
            return applicationContext.getBean(type);
        } catch (NoUniqueBeanDefinitionException e) {   //出現多個,選第一個
            String beanName = applicationContext.getBeanNamesForType(type)[0];
            return applicationContext.getBean(beanName, type);
        }
    }

    public static <T> T getBean(String beanName, Class<T> type) {
        return applicationContext.getBean(beanName, type);
    }
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM