Spring Boot 应用启动后调用方法

Posted

技术标签:

【中文标题】Spring Boot 应用启动后调用方法【英文标题】:Call a method after Spring Boot app starts 【发布时间】:2019-09-16 09:29:28 【问题描述】:

我有一个 Java Spring Boot 应用程序,它有一个调度程序,它从服务调用异步任务该任务需要几分钟(通常 3-5 分钟)才能完成。

服务中的相同异步方法也可以通过 UI 应用程序调用,方法是从 Spring Boot Controller 调用 API。

代码:

调度器

@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 Boot 应用程序以及重新启动时重置 DB 中的标志。

我该怎么做?有没有办法在 Spring Boot 应用程序启动后运行一个方法,从那里我可以从我的 Repo 调用一个方法来取消设置数据库中的标志?

【问题讨论】:

【参考方案1】:

检查@PostConstruct 例如这里https://www.baeldung.com/running-setup-logic-on-startup-in-spring

【讨论】:

谢谢!这正是我想要的。【参考方案2】:

如果您想在整个应用程序启动并准备好使用下面的示例 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

如果在创建单个 bean 后挂钩就足够了,请按照 @loan M 的建议使用 @PostConstruct

【讨论】:

【参考方案3】:

在您的特定情况下,您需要在应用程序部署后重置数据库,因此最好的方法是使用 Spring CommandLineRunner

Spring boot 提供了一个带有回调 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

【讨论】:

以上是关于Spring Boot 应用启动后调用方法的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot-运行部署

重启 Spring Boot 应用程序后第一次调用缓慢

Spring Boot启动流程代码断点分析

Spring Boot 微服务异步调用 @EnableAsync @Async

spring boot调用加密狗

Spring Boot REST 应用测试方法