我有一个使用以下配置公开 WebSocket 端点的应用程序
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
public static final String WS_ENDPOINT = "/notifications/v1";
public static final String EVENTS_CHANNEL = "/events";
public static final String ERRORS_CHANNEL = "/errors";
@Autowired
private StompMessageChannelInterceptor stompMessageChannelInterceptor;
@Override
public void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint(WS_ENDPOINT)
.setAllowedOrigins("*")
.addInterceptors(new WebsocketHandshakeInterceptor())
.setHandshakeHandler(new WebsocketHandshakeInterceptor());
}
@Override
public void configureMessageBroker(final MessageBrokerRegistry registry) {
registry.enableSimpleBroker(EVENTS_CHANNEL, ERRORS_CHANNEL);
}
@Override
public void configureClientInboundChannel(final ChannelRegistration registration) {
registration.interceptors(stompMessageChannelInterceptor);
}
@Override
public void configureWebSocketTransport(final WebSocketTransportRegistration registration) {
registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {
@Override
public WebSocketHandler decorate(final WebSocketHandler webSocketHandler) {
return new WebSocketSessionCapturingHandlerDecorator(webSocketHandler);
}
});
}
}
该配置在 Spring Boot 2.7.18 上运行良好。但迁移到 Spring Boot 3.3.5 后,
WebSocketMessagingAutoConfiguration
设置 AsyncTaskExecutor
。自动配置(在 WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration
中)采用了我们自定义的 AsyncTaskExecutor
实现,这不适合 WebSocket 配置(它为可运行任务添加了一些额外的逻辑)。下面是自动配置拾取的AsyncTaskExecutor
的实现
public class ApiPoolExecutor extends ThreadPoolTaskExecutor {
private static final long serialVersionUID = 1L;
@Override
public Future<?> submit(final Runnable task) {
return super.submit(new SomeLogicForRunnable(task));
}
@Override
public ListenableFuture<?> submitListenable(final Runnable task) {
return super.submitListenable(new SomeLogicForRunnable(task));
}
@Override
public <T> ListenableFuture<T> submitListenable(final Callable<T> task) {
return super.submitListenable(new SomeLogicForRunnable(task));
}
@Override
public void execute(final Runnable task) {
super.execute(new SomeLogicForRunnable(task));
}
}
我尝试创建
AsyncTaskExecutor
的另一个实现,没有围绕可运行任务的任何额外逻辑,但 Autoconfiguration
仍然只看到 ApiPoolExecutor 实现。我还尝试将执行器直接设置在我的ChannelRegistration
中的
WebSocketConfig
上
@Override
public void configureClientInboundChannel(final ChannelRegistration registration) {
registration.interceptors(stompMessageChannelInterceptor);
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100);
executor.setCorePoolSize(100);
executor.setBeanName("ws-pool-exec");
executor.initialize();
registration.executor(new WebSocketTaskPoolExecutor());
}
但稍后自动配置会使用
ApiPoolExecutor
覆盖该执行器。如何使自动配置不覆盖ChannelRegistration
上的执行器?或者如何完全禁用它?
我通过创建自己的 ThreadPoolTaskExecutor 作为命名 bean 来修复它。 Bean 名称应与 WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration 类中的 certainAsyncTaskExecutor() 方法所需的名称相对应
@Bean (name = TaskExecutionAutoConfiguration.APPLICATION_TASK_EXECUTOR_BEAN_NAME)
public ThreadPoolTaskExecutor getApplicationTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(100);
executor.setCorePoolSize(100);
executor.setBeanName("ws-pool-exec");
executor.initialize();
return executor;
}