【问题标题】:Call a method after Spring Boot app startsSpring Boot 应用启动后调用方法
【发布时间】: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 调用一个方法来取消设置数据库中的标志?

【问题讨论】:

    标签: java spring spring-boot scheduled-tasks


    【解决方案1】:

    【讨论】:

    • 谢谢!这正是我想要的。
    【解决方案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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-19
        • 2018-10-31
        • 2023-03-09
        • 2020-06-27
        • 2015-05-10
        • 2020-08-04
        相关资源
        最近更新 更多