Spring Websocket+SockJS+STOMP 实现即时通信(五)—— ChannelInterceptor与ExecutorChannelInterceptor

文章目录

    • ChannelInterceptor:
    • ExecutorChannelInterceptor:
        • 这里以,为InboundChannel配置ChannelInterceptor为例


ChannelInterceptor:

  • Message被发送到线程池,在发送动作执行前(后)拦截,发生在当前线程。

ExecutorChannelInterceptor:

  • Message被发送到线程池后,在线程池持有的新线程中,在MessageHandler处理前(后)拦截。

这里以,为InboundChannel配置ChannelInterceptor为例

  1. 在WebSocketMessageBrokerConfigurer中配置拦截器:
WebSocketMessageBrokerConfigurer:
 @Override
	
     
      public
      
     
      void
      
     
      configureClientInboundChannel
     (ChannelRegistration registration) {
		registration.
     
      interceptors
     (new 
     
      ChannelInterceptor
     () {
			 @Override
			 
     
      public
      Message<?> 
     
      preSend
     (Message<?> message, MessageChannel channel) {
			        StompHeaderAccessor accessor = MessageHeaderAccessor.
     
      getAccessor
     (message, StompHeaderAccessor.
     
      class
     );
			        StompCommand command = accessor.
     
      getCommand
     ();
			        log.
     
      info
     (command.
     
      toString
     ());
			        log.
     
      info
     (JSON.
     
      toJSONString
     (message));
			        if (StompCommand.CONNECT.
     
      equals
     (accessor.
     
      getCommand
     ())) {
			        	//群聊:表示roomId;私聊:表示userId
			        	String id = accessor.
     
      getFirstNativeHeader
     ("id");
			        	accessor.
     
      setUser
     (new 
     
      IdPrincipal
     (id));
			        }
			        
     
      return
      message;
			 }

		});
	}
  1. 从WebSocketMessageBrokerConfigurer配置中读取登记过的拦截器
AbstractMessageBrokerConfiguration:
	@Bean
	
     
      public
      AbstractSubscribableChannel 
     
      clientInboundChannel
     () {
		ExecutorSubscribableChannel channel = new 
     
      ExecutorSubscribableChannel
     (
     
      clientInboundChannelExecutor
     ());
		ChannelRegistration reg = 
     
      getClientInboundChannelRegistration
     ();
		if (reg.
     
      hasInterceptors
     ()) {
			channel.
     
      setInterceptors
     (reg.
     
      getInterceptors
     ());
		}
		
     
      return
      channel;
	}
  1. 将通道拦截器绑定到ExecutorSubscribableChannel上,同时为拦截器分类ChannelInterceptorExecutorChannelInterceptor,添加到相应集合中
ExecutorSubscribableChannel:
	@Override
	
     
      public
      
     
      void
      
     
      setInterceptors
     (List<
     
      ChannelInterceptor
     > interceptors) {
		
     
      super
     .
     
      setInterceptors
     (interceptors);
		
     
      this
     .executorInterceptors.
     
      clear
     ();
		for (ChannelInterceptor interceptor : interceptors) {
			if (interceptor 
     
      instanceof
      
     
      ExecutorChannelInterceptor
     ) {
				
     
      this
     .executorInterceptors.add((ExecutorChannelInterceptor) interceptor);
			}
		}
	}
  1. 普通的ChannelInterceptor,被内部类AbstractMessageChannel$ChannelInterceptorChain构造成拦截器链,这个拦截器链的所有实现方法都以外部类AbstractMessageChannel实例所持有的interceptors集合为核心,进行拦截器的调用。
  2. 拦截器链的调用发生在AbstractMessageChannel实例的send方法中,在sendInternal方法执行前后同步调用,发生在当前线程。
AbstractMessageChannel:


     
      public
      
     
      abstract
      
     
      class
      
     
      AbstractMessageChannel
      
     
      implements
      
     
      MessageChannel
     , InterceptableChannel, BeanNameAware {

	
     
      private
      
     
      final
      List<
     
      ChannelInterceptor
     > interceptors = new 
     
      ArrayList
     <
     
      ChannelInterceptor
     >(5);

	@Override
	
     
      public
      
     
      final
      
     
      boolean
      
     
      send
     (Message<?> message, 
     
      long
      timeout) {
		Assert.
     
      notNull
     (message, "
     
      Message
      
     
      must
      
     
      not
      be 
     
      null
     ");
		ChannelInterceptorChain chain = new 
     
      ChannelInterceptorChain
     ();
		
     
      boolean
      sent = 
     
      false
     ;
		try {
			message = chain.
     
      applyPreSend
     (message, 
     
      this
     );
			if (message == null) {
				
     
      return
      
     
      false
     ;
			}
			sent = 
     
      sendInternal
     (message, timeout);
			chain.
     
      applyPostSend
     (message, 
     
      this
     , sent);
			chain.
     
      triggerAfterSendCompletion
     (message, 
     
      this
     , sent, null);
			
     
      return
      sent;
		}
		
     
      catch
      (
     
      Exception
      ex) {
			chain.
     
      triggerAfterSendCompletion
     (message, 
     
      this
     , sent, ex);
			if (ex 
     
      instanceof
      
     
      MessagingException
     ) {
				
     
      throw
      (MessagingException) ex;
			}
			
     
      throw
      new 
     
      MessageDeliveryException
     (message,"
     
      Failed
      to 
     
      send
      
     
      message
      to " + 
     
      this
     , ex);
		}
		
     
      catch
      (
     
      Throwable
      err) {
			MessageDeliveryException ex2 =
					new 
     
      MessageDeliveryException
     (message, "
     
      Failed
      to 
     
      send
      
     
      message
      to " + 
     
      this
     , err);
			chain.
     
      triggerAfterSendCompletion
     (message, 
     
      this
     , sent, ex2);
			
     
      throw
      ex2;
		}
	}

	/**
	 * 
     
      Assists
      
     
      with
      
     
      the
      
     
      invocation
      of 
     
      the
      
     
      configured
      
     
      channel
      
     
      interceptors
     .
	 */
	
     
      protected
      
     
      class
      
     
      ChannelInterceptorChain
      {
		
     
      private
      int sendInterceptorIndex = -1;
		
     
      private
      int receiveInterceptorIndex = -1;
		
		
     
      public
      Message<?> 
     
      applyPreSend
     (Message<?> message, MessageChannel channel) {
			Message<?> messageToUse = message;
			for (ChannelInterceptor interceptor : interceptors) {
				Message<?> resolvedMessage = interceptor.
     
      preSend
     (messageToUse, channel);
				if (resolvedMessage == null) {
					String name = interceptor.
     
      getClass
     ().
     
      getSimpleName
     ();
					if (logger.
     
      isDebugEnabled
     ()) {
						logger.
     
      debug
     (name + " 
     
      returned
      
     
      null
      
     
      from
      
     
      preSend
     , i.e. 
     
      precluding
      
     
      the
      
     
      send
     .");
					}
					
     
      triggerAfterSendCompletion
     (messageToUse, channel, 
     
      false
     , null);
					
     
      return
      null;
				}
				messageToUse = resolvedMessage;
				
     
      this
     .sendInterceptorIndex++;
			}
			
     
      return
      messageToUse;
		}
		
     
      public
      
     
      void
      
     
      applyPostSend
     (Message<?> message, MessageChannel channel, 
     
      boolean
      sent) {
			for (ChannelInterceptor interceptor : interceptors) {
				interceptor.
     
      postSend
     (message, channel, sent);
			}
		}
      
        /**
         *其他方法
         */
	}

}
  1. InboundChannel实例通过sendInternal方法,将Message与MessageHandler封装成SendTask,发送到支撑自己的ThreadPoolTaskExecutor线程池,在新的线程中异步处理Message;
  2. 在新的线程中,在SendTask的run方法里,通过MessageHandler.handleMessage(Message)方法对Message进行处理,在handleMessage前后调用executorInterceptors集合,进行拦截;
ExecutorSubscribableChannel :


     
      public
      
     
      class
      
     
      ExecutorSubscribableChannel
      
     
      extends
      
     
      AbstractSubscribableChannel
      {
	
     
      private
      
     
      final
      Executor executor;
	
     
      private
      
     
      final
      List<
     
      ExecutorChannelInterceptor
     > executorInterceptors = new 
     
      ArrayList
     <
     
      ExecutorChannelInterceptor
     >(4);
	
	@Override
	
     
      public
      
     
      boolean
      
     
      sendInternal
     (Message<?> message, 
     
      long
      timeout) {
		for (MessageHandler handler : 
     
      getSubscribers
     ()) {
			SendTask sendTask = new 
     
      SendTask
     (message, handler);
			if (
     
      this
     .executor == null) {
				sendTask.run();
			}
			
     
      else
      {
				
     
      this
     .executor.
     
      execute
     (sendTask);
			}
		}
		
     
      return
      
     
      true
     ;
	}
	/**
	 * 
     
      Invoke
      a 
     
      MessageHandler
      
     
      with
      
     
      ExecutorChannelInterceptors
     .
	 */
	
     
      private
      
     
      class
      
     
      SendTask
      
     
      implements
      
     
      MessageHandlingRunnable
      {
		@Override
		
     
      public
      
     
      void
      run() {
			Message<?> message = 
     
      this
     .inputMessage;
			try {
				message = 
     
      applyBeforeHandle
     (message);
				if (message == null) {
					
     
      return
     ;
				}
				
     
      this
     .messageHandler.
     
      handleMessage
     (message);
				
     
      triggerAfterMessageHandled
     (message, null);
			}
			
     
      catch
      (
     
      Exception
      ex) {
				
     
      triggerAfterMessageHandled
     (message, ex);
				if (ex 
     
      instanceof
      
     
      MessagingException
     ) {
					
     
      throw
      (MessagingException) ex;
				}
				String description = "Failed to handle " + message + " to " + 
     
      this
      + " in " + 
     
      this
     .messageHandler;
				
     
      throw
      new 
     
      MessageDeliveryException
     (message, description, ex);
			}
			
     
      catch
      (
     
      Throwable
      err) {
				String description = "Failed to handle " + message + " to " + 
     
      this
      + " in " + 
     
      this
     .messageHandler;
				MessageDeliveryException ex2 = new 
     
      MessageDeliveryException
     (message, description, err);
				
     
      triggerAfterMessageHandled
     (message, ex2);
				
     
      throw
      ex2;
			}
		}

		
     
      private
      Message<?> 
     
      applyBeforeHandle
     (Message<?> message) {
			Message<?> messageToUse = message;
			for (ExecutorChannelInterceptor interceptor : executorInterceptors) {
				messageToUse = interceptor.
     
      beforeHandle
     (messageToUse, ExecutorSubscribableChannel.
     
      this
     , 
     
      this
     .messageHandler);
				if (messageToUse == null) {
					String name = interceptor.
     
      getClass
     ().
     
      getSimpleName
     ();
					if (logger.
     
      isDebugEnabled
     ()) {
						logger.
     
      debug
     (name + " 
     
      returned
      
     
      null
      
     
      from
      
     
      beforeHandle
     , i.e. 
     
      precluding
      
     
      the
      
     
      send
     .");
					}
					
     
      triggerAfterMessageHandled
     (message, null);
					
     
      return
      null;
				}
				
     
      this
     .interceptorIndex++;
			}
			
     
      return
      messageToUse;
		}

		
     
      private
      
     
      void
      
     
      triggerAfterMessageHandled
     (Message<?> message, Exception ex) {
			for (int i = 
     
      this
     .interceptorIndex; i >= 0; i--) {
				ExecutorChannelInterceptor interceptor = executorInterceptors.get(i);
				try {
					interceptor.
     
      afterMessageHandled
     (message, ExecutorSubscribableChannel.
     
      this
     , 
     
      this
     .messageHandler, ex);
				}
				
     
      catch
      (
     
      Throwable
      ex2) {
					logger.
     
      error
     ("
     
      Exception
      
     
      from
      
     
      afterMessageHandled
      in " + interceptor, ex2);
				}
			}
		}
	}

}

你可能感兴趣的:(Spring,Websocket)