Skip to content

拦截 (Interception)

虽然事件提供了对 STOMP 连接生命周期的通知,但它们并不针对每一条客户端消息。如果你需要对每一条流入或流出的消息进行处理,可以注册 ChannelInterceptor

注册拦截器

你可以拦截从客户端进入服务器的消息(Inbound):

java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

	@Override
	public void configureClientInboundChannel(ChannelRegistration registration) {
		registration.interceptors(new MyChannelInterceptor());
	}
}
kotlin
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {

	override fun configureClientInboundChannel(registration: ChannelRegistration) {
		registration.interceptors(MyChannelInterceptor())
	}
}

实现拦截器

自定义拦截器可以利用 StompHeaderAccessorSimpMessageHeaderAccessor 来访问消息信息:

java
public class MyChannelInterceptor implements ChannelInterceptor {

	@Override
	public Message<?> preSend(Message<?> message, MessageChannel channel) {
		StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
		StompCommand command = accessor.getCommand();
		// 根据命令(如 CONNECT, SEND, SUBSCRIBE)执行逻辑
		return message;
	}
}
kotlin
class MyChannelInterceptor : ChannelInterceptor {

	override fun preSend(message: Message<*>, channel: MessageChannel): Message<*>? {
		val accessor = StompHeaderAccessor.wrap(message)
		val command = accessor.command
		// 逻辑处理
		return message
	}
}

线程内拦截 (ExecutorChannelInterceptor)

你还可以实现 ExecutorChannelInterceptor(它是 ChannelInterceptor 的子接口)。与普通拦截器不同,它的回调发生在消息被实际处理的那个线程中,而不是发送消息的线程。


补充教学

1. 消息过滤

通过在 preSend 中返回 null,你可以拦截并“吃掉”某条消息,使其永远不会到达 Controller 或代理。这常用于黑名单过滤或非法内容检测。

2. 用户身份“盖章”

如果你在 CONNECT 帧拦截器中手动验证了用户,别忘了通过 accessor.setUser(user) 将 User 对象设置进消息。Spring 会自动将这个 User 传递到后续该 Session 的所有消息中,你在 Controller 里就能直接拿到了。

3. 多重拦截器

你可以注册多个拦截器,它们会形成一个拦截器链。执行顺序取决于你添加它们的先后顺序。

Based on Spring Framework.