zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
    
    
  • 相关阅读:
    关于lua扩展库lpack的使用指南
    mac下安装LuaSocket
    lua_の_进阶总结之基础篇
    minicap_工具使用
    AutoSense脚本日志总结(微信搜索【水勺子】公众号获取详情)
    六:Spring Security 中使用 JWT
    五:Spring Security 中的角色继承问题
    四:Spring Security 登录使用 JSON 格式数据
    二:整合Spring Security
    三:Spring Security 登录添加验证码
  • 原文地址:https://www.cnblogs.com/cnsyear/p/12635372.html
Copyright © 2011-2022 走看看