计划任务无法使用Websockets工作

10

我有一个使用WebSockets的Spring Boot应用程序:

@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
@EnableScheduling
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

WebSocket配置:

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
        webSocketHandlerRegistry.addHandler(socketHandler(), "/connect/*")
                .setAllowedOrigins("*")
                .addInterceptors(handshakeInterceptor());
    }

    @Bean
    public WebSocketHandler socketHandler() {
        return new CustomHandler();
    }

    @Bean
    public HandshakeInterceptor handshakeInterceptor() {
        return new CustomInterceptor();
    }    
}

它运行得很好。然后我添加了@EnableSheduled并创建了调度组件:

@Component
public class ScheduledTask {

    @Scheduled(fixedRate = 1000)
    public void printHello() {
        System.out.println("hello");
    }
}

并且会收到一个异常:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'defaultSockJsTaskScheduler' is expected to be of type 'org.springframework.scheduling.TaskScheduler' but was actually of type 'org.springframework.beans.factory.support.NullBean'
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:392) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1116) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1083) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:313) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:254) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:231) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:103) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163) ~[spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552) ~[spring-context-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.5.BUILD-20190515.065035-40.jar:2.1.5.BUILD-SNAPSHOT]
    at ru.test.project.TestApplication.main(TestApplication.java:17) [classes/:na]

我尝试从我的项目中移除WebSockets。之后,一切开始正常工作了。如何解决这个问题?

I tried to remove websockets from my project. After this, everything starts works fine. How to fix it?

3个回答

14

谢谢!实际上,调度程序的类型也需要是ThreadPoolTaskScheduler,以便访问setPoolSize等功能:@Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); scheduler.setPoolSize(2); scheduler.setThreadNamePrefix("scheduled-task-"); scheduler.setDaemon(true); return scheduler; } - Stefan

9

除了Michel的采纳答案外:

在使用Spring Boot时,建议使用构建器来创建TaskScheduler,而不是直接创建TaskScheduler:

@Bean
public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
    return builder.build();
}

该构建器定义在org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration中。因此,使用这种方法,您将获得与不使用@EnableWebSocket完全相同的调度程序(即它将使用来自Spring配置属性的池大小等)。

0

有一种更方便的方法来解决这个问题。 您可以使用@Configurable@EnableScheduling注释您的自定义调度程序类,并在其中实现SchedulingConfigurer接口。 然后,您应该实现具有ScheduledTaskRegistrar对象作为其输入参数的configureTasks方法。 使用此对象,您可以定义和执行任何类型的定期任务。 只需记住,您需要在父Bean中通知Spring Framework上下文。

父Bean类的构造函数:

public ParentBean() {
        new AnnotationConfigApplicationContext(MyTaskScheduler.class);
}

MyTaskScheduler 类:

@Configurable
@EnableScheduling
public class MyTaskScheduler implements SchedulingConfigurer {
    @Override
    public void configureTasks (ScheduledTaskRegistrar taskRegistrar) {
        // -- Schedule task #1  --
        taskRegistrar.addFixedDelayTask(() -> { firstTask(); }, 10000);

        // -- Schedule task #2 --
        taskRegistrar.addFixedRateTask(() -> { secondTask(); }, 1000);
    }

    private void firstTask() {
        // -- Your first task logic goes here! --
    }

    private void secondTask() {
        // -- Your second task logic goes here! --
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接