2016-12-02 134 views
2

我正在写一个Spring-Boot应用程序来监视一个目录并处理正在添加的文件。我注册WatchService的目录中配置类:如何中止Spring-Boot启动?

@Configuration 
public class WatchServiceConfig { 

    private static final Logger logger = LogManager.getLogger(WatchServiceConfig.class); 

    @Value("${dirPath}") 
    private String dirPath; 

    @Bean 
    public WatchService register() { 
     WatchService watchService = null; 

     try { 
      watchService = FileSystems.getDefault().newWatchService(); 
      Paths.get(dirPath).register(watchService, ENTRY_CREATE); 
      logger.info("Started watching \"{}\" directory ", dlsDirPath); 
     } catch (IOException e) { 
      logger.error("Failed to create WatchService for directory \"" + dirPath + "\"", e); 
     } 

     return watchService; 
    } 
} 

我想优雅地放弃春节引导启动,如果注册目录失败。有人知道我能做到吗?

+0

您是否试过'System.exit(SIGNUM)' – Turtle

+0

我宁愿优雅地去做。 System.stop()立即杀死** JVM **。 –

+0

然后'RuntimeException'? – Turtle

回答

1

获取应用程序环境,如:

@Autowired 
private ConfigurableApplicationContext ctx; 

然后调用close方法,如果你不能找到目录:

ctx.close(); 

那优雅关机的应用程序环境,因此,弹簧引导应用程序本身。

更新

的更详细的例子基于在问题提供的代码。

主类

@SpringBootApplication 
public class GracefulShutdownApplication { 

    public static void main(String[] args) { 
     ConfigurableApplicationContext ctx = SpringApplication.run(GracefulShutdownApplication.class, args); 
     try{ 
      ctx.getBean("watchService"); 
     }catch(NoSuchBeanDefinitionException e){ 
      System.out.println("No folder to watch...Shutting Down"); 
      ctx.close(); 
     } 
    } 

} 

WatchService配置

@Configuration 
public class WatchServiceConfig { 

    @Value("${dirPath}") 
    private String dirPath; 

    @Conditional(FolderCondition.class) 
    @Bean 
    public WatchService watchService() throws IOException { 
     WatchService watchService = null; 
     watchService = FileSystems.getDefault().newWatchService(); 
     Paths.get(dirPath).register(watchService, ENTRY_CREATE); 
     System.out.println("Started watching directory"); 
     return watchService; 
    } 

文件夹条件

public class FolderCondition implements Condition{ 

    @Override 
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { 
     String folderPath = conditionContext.getEnvironment().getProperty("dirPath"); 
     File folder = new File(folderPath); 
     return folder.exists(); 
    } 
} 

充分利用WatchService豆@Conditional基于目录是否存在或不存在。然后在你的主类中,检查WatchService Bean是否存在,如果不是通过调用close()关闭应用程序上下文。

+0

我试过这个,但是当调用'ctx.close()'时得到这个异常:'java.lang.IllegalStateException:LifecycleProcessor未初始化 - 在通过上下文调用生命周期方法之前调用'refresh':org.springframework.context.annotation 。AnnotationConfigApplicationContext @ 385e9564:启动日期[Fri Dec 02 16:45:12 EST 2016];上下文层次结构的根' –

+0

然后我添加了'ctx.refresh()',事情变得更糟了:'org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为'application'的bean时出错:通过字段'directoryMonitorService'表示的不满意的依赖项; ' –

+0

@ZhubinSalehi我已经添加了一个更详细的示例,显示如何以及在哪里调用close()方法。希望有所帮助。 –

0

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-exit

每个SpringApplication将注册与JVM到 关闭挂钩确保ApplicationContext需要在退出正常关闭。所有的 都可以使用标准的Spring生命周期回调(如DisposableBean 接口或@PreDestroy注释)。

另外,如果bean在应用程序结束时希望 返回特定的退出代码,则它们可以实现 org.springframework.boot.ExitCodeGenerator接口。

您应该实施释放资源/文件的@PreDestroy方法。然后在启动过程中,当您检测到一些错误时,您可以抛出一些异常 - 它会开始关闭应用程序上下文。