账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    springboot2结合websocket时为何ChannelInterceptorAdapter无法注入bean?
    28
    0
    package com.qky.qingchi.config;
    
    import com.qky.qingchi.config.filter.UserMessageInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.messaging.simp.config.ChannelRegistration;
    import org.springframework.messaging.simp.config.MessageBrokerRegistry;
    import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
    import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
    import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
    
    @Configuration
    @EnableWebSocketMessageBroker
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        @Override
        public void configureMessageBroker(MessageBrokerRegistry registry) {
            registry.enableSimpleBroker("/queue", "/topic");
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/webSocketServer").setAllowedOrigins("*").withSockJS();
        }
    
        /**
         * 配置客户端入站通道拦截器
         */
        @Override
        public void configureClientInboundChannel(ChannelRegistration registration) {
            registration.interceptors(new UserMessageInterceptor());
        }
    }
    
    package com.qky.qingchi.config.filter;
    
    import com.qky.qingchi.config.websocket.WebSocketUser;
    import com.qky.qingchi.util.TokenUtils;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.listener.ChannelTopic;
    import org.springframework.data.redis.listener.RedisMessageListenerContainer;
    import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
    import org.springframework.messaging.Message;
    import org.springframework.messaging.MessageChannel;
    import org.springframework.messaging.simp.stomp.StompCommand;
    import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
    import org.springframework.messaging.support.ChannelInterceptorAdapter;
    import org.springframework.messaging.support.MessageHeaderAccessor;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    @Component
    public class UserMessageInterceptor extends ChannelInterceptorAdapter {
    
        @Resource
        private RedisMessageListenerContainer redisContainer;
    
        @Resource
        private RedisConnectionFactory connectionFactory;
    
        @Resource
        private MessageListenerAdapter messageListener;
    
        @Resource
        private ChannelTopic topic;
    
        @Resource
        private String qkyname;
    
        /**
         * 获取包含在stomp中的用户信息
         */
        @Override
        public Message<?> preSend(Message<?> message, MessageChannel channel) {
            StompHeaderAccessor accessor =
                    MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
            System.out.println(accessor.getLogin());
            System.out.println(accessor.getCommand());
            System.out.println("-----------------------");
            System.out.println(redisContainer);
            System.out.println(messageListener);
            System.out.println(topic);
            System.out.println(qkyname);
            System.out.println("-----------------------");
            System.out.println("触发websocket连接");
            //1. 判断是否首次连接请求
            if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                //2. 验证是否登录
                String token = accessor.getNativeHeader("token").get(0);
                System.out.println(token);
                if (TokenUtils.isCorrect(token)) {
                    String phoneNumber = TokenUtils.getPhoneNumByToken(token);
                    accessor.setUser(new WebSocketUser(phoneNumber));
                /*    RedisMessageListenerContainer container = new RedisMessageListenerContainer();
                    container.setConnectionFactory(connectionFactory);
                    container.addMessageListener(messageListener, new ChannelTopic(phoneNumber));*/
                    return message;
                } else {
                    return null;
                }
            }
            //不是首次连接,已经成功登陆
            return message;
        }
    }
    package com.qky.qingchi.config.redis;
    
    import com.qky.qingchi.util.UserUtils;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.MessageListener;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.listener.ChannelTopic;
    import org.springframework.data.redis.listener.RedisMessageListenerContainer;
    import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
    import org.springframework.messaging.simp.SimpMessagingTemplate;
    
    import javax.annotation.Resource;
    
    @Configuration
    public class RedisSubListenerConfig {
    
        @Resource
        private SimpMessagingTemplate messagingTemplate;
    
        @Bean
        MessageListenerAdapter messageListener() {
            //abstract methods overwrite
            return new MessageListenerAdapter((MessageListener) (message, pattern) -> {
                System.out.println("Message received: " + message.toString());
                //message中带user信息,然后根据user推送message
    //            replyUser.getUsername()
                messagingTemplate.convertAndSendToUser(UserUtils.getUser().getPhoneNum(), "/queue/notifications", message);
            });
        }
    
        @Bean
        RedisMessageListenerContainer redisContainer(RedisConnectionFactory connectionFactory) {
            RedisMessageListenerContainer container
                    = new RedisMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.addMessageListener(messageListener(), topic());
            return container;
        }
    
        @Bean
        ChannelTopic topic() {
            return new ChannelTopic("messageQueue");
        }
    
        @Bean("qkyname")
        public String qkyname() {
            System.out.println("注册秦开远名字bean");
            return "qinkaiyuan";
        }
    }

    注入的内容在其他类都是可以获得的,就在这个类里面无法获取,这是为什么啊

    0
    打赏
    收藏
    点击回答
    您的回答被采纳后将获得:提问者悬赏的 11 元积分
        全部回答
    • 0
    • 年少总有装逼梦 普通会员 1楼

      在Spring Boot 2中,ChannelInterceptorAdapter(在配置channelInterceptor属性时添加的Interceptor)无法注入bean的原因可能有以下几点:

      1. 缺乏合适的依赖注入配置:ChannelInterceptorAdapter通常依赖于Spring的WebFlux或ChromotingIoC等依赖注入机制,如果你的项目中没有正确地配置这些依赖,ChannelInterceptorAdapter可能无法找到对应的bean实例。例如,如果你在配置类中没有添加如下依赖:

      ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Value; import org.springframework.web.client.WebClient; import org.springframework.web.socket.client.WebSocketClient;

      @Configuration public class ChannelInterceptorConfig { @Value("${spring.web.socket.client.acceptors}") private String acceptors;

      @Bean
      public WebSocketClient client() {
          return new WebSocketClientBuilder()
                  .setAcceptors(acceptors)
                  .build();
      }
      

      } ```

      在上述配置中,WebSocketClient是ChannelInterceptorAdapter依赖的Bean,如果没有在ClientBuildersetAcceptors方法中注入对应的acceptors参数,那么ChannelInterceptorAdapter就无法获取到对应的WebSocketClient对象,从而无法注入bean。

      1. ChannelInterceptorAdapter接口定义问题:在ChannelInterceptorAdapter的@Configuration注解中,需要明确指出@Bean注解要注入的bean实例。例如,如果你的ChannelInterceptorAdapter接口定义为:

      java public class ChannelInterceptorAdapter implements ChannelInterceptor { // ... }

      那么在你的ChannelInterceptorConfig类中,你需要添加如下依赖:

      ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Value; import org.springframework.web.client.WebClient; import org.springframework.web.socket.client.WebSocketClient;

      @Configuration public class ChannelInterceptorConfig { @Value("${spring.web.socket.client.acceptors}") private String acceptors;

      @Bean
      public WebSocketClient client() {
          return new WebSocketClientBuilder()
                  .setAcceptors(acceptors)
                  .build();
      }
      

      } ```

      此时,ChannelInterceptor接口定义如下:

      java @Configuration public interface ChannelInterceptor { @Bean WebSocketClient client(); }

      这样,ChannelInterceptorAdapter才能正确地注入对应的WebSocketClient对象,从而实现WebSocket通信的功能。

      1. 缺少具体的ChannelInterceptor实现:ChannelInterceptorAdapter实现的具体类型需要与你期望注入的bean实例类型相匹配。例如,如果你的bean实例类型是WebSocketClient,那么你需要在ChannelInterceptorAdapter中实现org.springframework.web.socket.client.WebSocketClient接口,而不是简单地使用org.springframework.web.socket.client.WebSocketClientBuilder

      例如,如果你的bean实例类型是WebSocketClient,你可以在ChannelInterceptorAdapter@Configuration注解中实现以下代码:

      ```java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Value; import org.springframework.web.client.WebClient; import org.springframework.web.socket.client.WebSocketClient;

      @Configuration public class ChannelInterceptorConfig { @Value("${spring.web.socket.client.acceptors}") private String acceptors;

      @Bean
      public WebSocketClient client() {
          return new WebSocketClientBuilder()
                  .setAcceptors(acceptors)
                  .build();
      }
      
      @Override
      public WebSocketClient createWebSocketClient() {
          return new WebSocketClientBuilder()
                  .setAcceptors(acceptors)
                  .build();
      }
      

      } ```

      在上述代码中,createWebSocketClient方法返回了与WebSocketClient接口相匹配的bean实例,从而实现了WebSocket通信的功能。

      总之,ChannelInterceptorAdapter无法注入bean的原因可能有多种,包括依赖注入配置、接口定义问题以及具体的ChannelInterceptor实现问题。要解决这个问题,你需要确保以下几点:

      1. 在配置类中正确地添加了ChannelInterceptor的依赖。
      2. 明确地定义了ChannelInterceptor接口,包括所需的实现类。
      3. ChannelInterceptorAdapter中实现了与WebSocketClient接口相匹配的bean实例,或者返回了与WebSocketClient接口相匹配的bean实例。
    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部