我有一个Java Spring Boot应用程序,它有一个调度程序从服务调用异步任务该任务需要几分钟(通常为3-5分钟)才能完成。
通过从Spring Boot Controller调用API,也可以通过UI应用程序调用Service中的相同异步方法。
码:
调度
@Component
public class ScheduledTasks {
@Autowired
private MyService myService;
@Scheduled(cron = "0 0 */1 * * ?")
public void scheduleAsyncTask() {
myService.doAsync();
}
}
服务
@Service
public class MyService {
@Async("threadTaskExecutor")
public void doAsync() {
//Do Stuff
}
}
调节器
@CrossOrigin
@RestController
@RequestMapping("/mysrv")
public class MyController {
@Autowired
private MyService myService;
@CrossOrigin
@RequestMapping(value = "/", method = RequestMethod.POST)
public void postAsyncUpdate() {
myService.doAsync();
}
}
调度程序每小时运行一次异步任务,但用户也可以从UI手动运行它。
但是,如果异步方法已经在执行过程中,我不希望再次运行异步方法。
为了做到这一点,我在DB中创建了一个表,其中包含一个标志,该标志在方法运行时继续,然后在方法完成后关闭。
我的服务类中有类似的东西:
@Autowired
private MyDbRepo myDbRepo;
@Async("threadTaskExecutor")
public void doAsync() {
if (!myDbRepo.isRunning()) {
myDbRepo.setIsRunning(true);
//Do Stuff
myDbRepo.setIsRunning(false);
} else {
LOG.info("The Async task is already running");
}
}
现在,问题是由于各种原因(应用程序重启,其他一些应用程序错误等),标志有时会卡住
因此,我想在每次部署Spring启动应用程序时重新启动时重置DB中的标志。
我怎样才能做到这一点?有没有办法在Spring Boot Application启动后运行一个方法,从那里我可以从我的Repo中调用一个方法来取消设置数据库中的标志?
检查@PostConstruct,例如https://www.baeldung.com/running-setup-logic-on-startup-in-spring
如果你想在整个应用程序启动后做一些事情并准备好使用下面的示例from
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ApplicationStartup
implements ApplicationListener<ApplicationReadyEvent> {
/**
* This event is executed as late as conceivably possible to indicate that
* the application is ready to service requests.
*/
@Override
public void onApplicationEvent(final ApplicationReadyEvent event) {
// here your code ...
return;
}
} // class
如果按照@loan M的建议,在单个bean创建后使用@PostConstruct
就足够了
在您的特定情况下,您需要在应用程序部署后重置数据库,因此最好的方法是使用Spring CommandLineRunner。
Spring引导提供了一个带有回调run()方法的CommanLineRunner接口,该方法可以在实例化Spring应用程序上下文后在应用程序启动时调用。
CommandLineRunner bean可以在同一个应用程序上下文中定义,可以使用@Ordered接口或@Order注释进行排序。
@Component
public class CommandLineAppStartupRunnerSample implements CommandLineRunner {
private static final Logger LOG =
LoggerFactory.getLogger(CommandLineAppStartupRunnerSample .class);
@Override
public void run(String...args) throws Exception {
LOG.info("Run method is executed");
//Do something here
}
}
网站上提到的答案:https://www.baeldung.com/running-setup-logic-on-startup-in-spring