2014-04-18 3 views
0

스프링 웹 응용 프로그램을 시작할 때 (예 : DB 버전이 예외임을 확인하는 등) 몇 가지 검사를 수행하려고합니다. 검사가 실패하면 서블릿은 페이지를 제공하지 못하도록 죽이게 (또는 시작하지 않는 것이 더 좋음)해야합니다. 이상적으로 Tomcat/Netty/서비스가 포함 된 것도 포함해야합니다 (더 까다 롭긴하지만).WebAppInitializer - 시작 오류시 종료하는 방법

내 시동 검사가 안전하게 종료되어야하는 많은 서비스 (예 : DB 연결 등)에 의존하기 때문에 System.exit를 호출 할 수 없습니다.

나는 this thread을 발견했는데, 이는 스프링 컨텍스트에서 close를 호출하는 것을 의미합니다. 그러나 예외보고를 제외하고는 봄이 기쁜 듯이 서블릿을 계속 시작합니다 (아래 참조).

Java Servlet 설명서를 살펴 봤는데 - 서블릿에서 파괴를 호출하지 않는다고합니다. 서블릿 객체가 스택 위로 올라와있는 메소드에서 Servlet.destroy를 호출할지 여부는 잘 모르겠습니다. (내 꼬리를 먹고 싶지 않아). 사실, 서블릿은 처음부터 만들어지지 않았습니다. 모든 웹 서비스를 시작하기 전에 시작시 검사를 먼저 실행하는 것이 좋습니다. 콩 초기화가 일어나는 동안 가까운 전화를 안하기 때문에 아마도

BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext. 

(새로 고침 가능성이 높습니다 : 여기

@Service 
class StartupCheckService extends InitializingBean { 

    @Autowired a:OtherServiceToCheckA = null 
    @Autowired b:OtherServiceToCheckB = null 

    override def afterPropertiesSet = { 
    try{ 

     checkSomeEssentialStuff(); 

    } catch { 
     case e: Any => { 

     // DON'T LET THE SERVICE START! 
     ctx = getTheContext(); 
     ctx.close(); 

     throw e; 
    } 
} 

닫기 호출이 오류가 발생합니다 ... 내가 가진 무엇 우리를 무한 루프에 빠지게한다). 여기 내 시작 코드 ...

class WebAppInitializer extends WebApplicationInitializer { 

    def onStartup(servletContext: ServletContext): Unit = { 

    val ctx = new AnnotationConfigWebApplicationContext() 

    // Includes StartupCheckService 
    ctx.register(classOf[MyAppConfig]) 
    ctx.registerShutdownHook() // add a shutdown hook for the above context... 


    // Can't access StartupCheckService bean here. 


    val loaderListener = new ContextLoaderListener(ctx) 
    // Make context listens for servlet events 
    servletContext.addListener(loaderListener) 

    // Make context know about the servletContext 
    ctx.setServletContext(servletContext) 

    val servlet: Dynamic = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(ctx)) 
    servlet.addMapping("/") 
    servlet.setLoadOnStartup(1) 
} 

내가 onStartup

ctx.refresh() 
val ss:StartupService = ctx.getBean(classOf[StartupCheckService]) 
ss.runStarupRountines() 

을 이런 종류의 일을 시도했지만 분명히 내가 onStartup 종료 될 때까지 새로 고침을 호출 할 수 아니에요입니다.

슬프게도 스프링의 무한대의 추상화 레이어로 인해이 간단한 문제로 인해 어려움을 겪을 수 있습니다. 일들이 초기화되는 순서에 관한 중요한 모든 세부 사항은 숨겨져 있습니다. 은 "그것을 구글에서해야"전에 나치가 도착

... BCDEAF

답변

1

난 당신이 WebApplicationInitializer에서이 작업을 수행 할 필요가 이유를 모르겠어요. 상태 확인을 수행하는 @Bean을 구성하려면 ApplicationListener<ContextRefreshedEvent>에서 수행하십시오. 거기에서 ConfigurableApplicationContext (이벤트 소스)에 액세스하여 닫을 수 있습니다. 그러면 Spring 컨텍스트가 종료됩니다. 서블릿과 웹 애플리케이션을 죽이려면 예외를 던집니다.

시작하지 않으면 컨테이너 (Tomcat 등)를 죽일 수 없습니다. 포함 된 컨테이너를 사용해 볼 수 있습니다 (예 : Spring Boot가 쉽게 처리 할 수 ​​있음).

1

내가 이해하는 한, 명시 적으로 close()을 호출 할 필요가 없습니다. 예외가 afterPropertiesSet()을 벗어나면 Spring은 나머지 빈 인스턴스를 자동으로 멈추고 전체 컨텍스트를 종료해야합니다.

지금까지 초기화 된 bean에 대한 정리를해야한다면 @PreDestroy을 사용할 수 있습니다.