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

版权声明:本文为博主原创文章,可以转载不可复制。 https://blog.csdn.net/qq_32331073/article/details/83411348


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);
				}
			}
		}
	}

}

猜你喜欢

转载自blog.csdn.net/qq_32331073/article/details/83411348
今日推荐