拦截 (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())
}
}实现拦截器
自定义拦截器可以利用 StompHeaderAccessor 或 SimpMessageHeaderAccessor 来访问消息信息:
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. 多重拦截器
你可以注册多个拦截器,它们会形成一个拦截器链。执行顺序取决于你添加它们的先后顺序。