我正在尝试定期在我的Spring MVC应用程序中运行一些作业。根据在线教程,我按如下方式设置计划作业:
这是应用程序初始值设定项(我在XML中没有设置(:
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(JPAConfiguration.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(MvcConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
这是配置文件:
@Configuration
@EnableScheduling
@EnableTransactionManagement
@ComponentScan(basePackages = {"com.prime.tutorials"})
@EnableJpaRepositories(basePackages = {"com.prime.tutorials.model", "com.prime.tutorials.repository"})
public class JPAConfiguration {
@Value("${jdbcURL}")
private transient String jdbcURL;
@Value("${dbPassword}")
private transient String dbPassword;
/* The usual stuff here, let me know if you want me post that as well */
}
这是处理计划作业的类:
@Service
public class ScheduledJobService {
@Autowired
private PrimeRepository primeRepository
@Scheduled(fixedDelayString = "${fixedDelay.in.milliseconds:10000}")
public void run() {
System.out.println("Current time is :: " + Calendar.getInstance().getTime());
}
}
如您所见,固定延迟设置为 10 秒,但我的工作每 5 秒运行一次。我不明白为什么会这样。我之前浏览了有关此主题的问题,但无法找到匹配的解决方案。
其他帖子表明,在这种情况下,豆子可能会初始化两次,但根据我的配置,我不确定这是怎么回事。
类似问题 上面的这个问题似乎与我所问的完全重复,但 OP 尚未发布他/她的配置或设置。大多数答案都建议对组件进行双重初始化,我不确定我的应用程序是否适合这种情况。
Current time is :: Sun Jun 10 22:53:16 EDT 2018
Current time is :: Sun Jun 10 22:53:22 EDT 2018
Current time is :: Sun Jun 10 22:53:26 EDT 2018
Current time is :: Sun Jun 10 22:53:32 EDT 2018
Current time is :: Sun Jun 10 22:53:36 EDT 2018
编辑-1
根据詹妮弗的建议,我确实看到两个实例正在调用 run 方法。
编辑-2
M.Deinum的猜测是绝对正确的,我的MvcConfig.java被@ComponentScan注释,这使得计划作业运行了两次。但是从 MvcConfig 中删除该注释后.java我的端点停止工作。我在这里错过了什么..
问题是您的JPAConfiguration
和MvcConfig
中可能具有相同的组件扫描。结果是你基本上加载了整个应用程序两次(所以除非你想遇到内存问题,奇怪的事务问题等,否则这是要走的路(。
你想要的是你的ContextLoaderListener
(根上下文(加载除 Web 相关 bean 之外的所有内容,DispatcherServlet
应该只加载与 Web 相关的 bean(视图、控制器、建议等(。
@ComponentScan
具有可用于控制此属性的属性。在JPAConfiguration
中添加一些excludeFilters
MvcConfig
禁用默认值并添加一些includeFilters
。
您的JPAConfiguration
@ComponentScan
应包含以下内容:
@ComponentScan(
basePackages = {"com.prime.tutorials"},
excludeFilters = {
@ComponentScan.Filter( { Controller.class, ControllerAdvice.class })
})
您的MvcConfig
您应该使用相同的includeFilters
,并禁用默认过滤器。
@ComponentScan(
basePackages = {"com.prime.tutorials"},
useDefaultFilters = false,
includeFilters = {
@ComponentScan.Filter( { Controller.class, ControllerAdvice.class })
})
您不想做不同的基本包,因为这会非常麻烦。恕我直言,您不应该使用技术分离作为创建包的一种方式(另请参阅 https://softwareengineering.stackexchange.com/questions/258196/java-application-structure-horizontal-vs-vertical-split/258197#258197(。
当您创建Scheduled
类的多个实例 (ScheduledJobService
( 时,通常会发生这种情况。一个常见的原因是 Spring 上下文被多次创建。
将此添加到 run 方法以查看您是否有多个实例:
public void run() {
System.out.println(this + " Current time is :: " + Calendar.getInstance().getTime());
}
您将能够在输出中看到其多个实例。
若要确保它不是属性值,请尝试不使用硬编码值 10000。
@Scheduled(fixedDelay = 10000)