2016-12-02 133 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方法。然後在啓動過程中,當您檢測到一些錯誤時,您可以拋出一些異常 - 它會開始關閉應用程序上下文。