在 Spring Boot WebSocket + STOMP 中,可以通过 MessageExceptionHandler 来捕捉处理消息发送/接收过程中出现的异常。MessageExceptionHandler 是一个接口,用于定义处理异常的方法。
Spring Boot 提供了默认的 MessageExceptionHandler 实现类,即 SimpleMessageHandlerExceptionResolver,它会将异常转换为 STOMP 错误消息,并发送给客户端。如果需要自定义异常捕捉和处理逻辑,可以实现 MessageExceptionHandler 接口,并注册到 WebSocket 配置类中。
以下是一个自定义 MessageExceptionHandler 的示例:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
// 注册自定义的 MessageExceptionHandler
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.addDecoratorFactory((connection, endpoint, headers) -> {
return new CustomMessageHandlerDecorator(connection);
});
}
private static class CustomMessageHandlerDecorator extends AbstractSessionWebSocketHandlerDecorator {
private final Logger logger = LoggerFactory.getLogger(CustomMessageHandlerDecorator.class);
public CustomMessageHandlerDecorator(WebSocketSession delegate) {
super(delegate);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
try {
super.handleMessage(session, message);
} catch (Throwable t) {
handleException(session, message, t);
}
}
private void handleException(WebSocketSession session, WebSocketMessage<?> message, Throwable t) throws Exception {
if (t instanceof MyCustomException) { // 自定义异常处理逻辑
logger.error("My custom exception occurred: {}", t.getMessage());
String errorMessage = "An error occurred: " + t.getMessage();
StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.ERROR);
headerAccessor.setMessage(errorMessage);
headerAccessor.setSessionId(session.getId());
headerAccessor.setDestination(((StompHeaderAccessor) message.getHeaders()).getDestination());
session.sendMessage(MessageBuilder.createMessage(new byte[0], headerAccessor.getMessageHeaders()));
} else {
throw t; // 交由 SimpleMessageHandlerExceptionResolver 处理
}
}
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/websocket").withSockJS();
}
}
在上述示例中,我们通过 WebSocketTransportRegistration 的 addDecoratorFactory 方法注册了一个自定义的装饰器类 CustomMessageHandlerDecorator,并重写了 handleMessage 方法来实现异常捕捉和处理逻辑。当出现 MyCustomException 异常时,会记录日志并发送 STOMP 错误消息给客户端;否则将异常抛出交由 SimpleMessageHandlerExceptionResolver 处理。
注意:如果自定义了 MessageExceptionHandler,需要将其注册到 WebSocket 配置类中,并且不能与 SimpleMessageHandlerExceptionResolver 同时使用。