[SPRING] 웹 응용 프로그램에 shutDownHook 등록
SPRING웹 응용 프로그램에 shutDownHook 등록
웹 응용 프로그램에서 시스템 종료 훅을 등록하는 방법은 무엇입니까?
web.xml 또는 applicationContext.xml에 등록 할 수있는 방법이 있습니까?
메인 클래스의 애플리케이션을 사용한다면 간단하다는 것을 알고 있습니다.
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
context.registerShutdownHook();
하지만 웹 응용 프로그램은 어떻습니까? ContextListener를 사용하므로
해결법
-
==============================
1.독립형 (비 웹) 응용 프로그램에서 registerShutdownHook () :
독립형 (비 웹) 응용 프로그램에서 registerShutdownHook () :
@PreDestroy 어노테이션은 Bean이 컨텍스트에서 제거 될 때 또는 컨텍스트가 종료 될 때 통지되도록 Bean 메소드에 사용됩니다.
종료 이벤트는 context.close () 또는 context.registerShutdownHook ()이 호출 될 때 발생합니다.
@Component(value="someBean") public class SomeBean { @PreDestroy public void destroy() { System.out.println("Im inside destroy..."); } }
당신이 이미 이것을 알고 있기를 바랍니다.
웹 응용 프로그램의 registerShutdownHook ()
웹 애플리케이션에서 DispatcherServlet / ContextListener는 ApplicationContext를 생성하고 서버가 종료되면 컨텍스트를 닫습니다. context.close () 또는 context.registerShutdownHook ()을 명시 적으로 호출 할 필요가 없습니다.
서버가 종료되면 Bean의 @PreDestory 메소드가 자동으로 통지됩니다.
-
==============================
2.웹 응용 프로그램에서 응용 프로그램을 배포 및 배포 취소 할 때 발생하는 ServletContextListener를 사용할 수 있습니다.
웹 응용 프로그램에서 응용 프로그램을 배포 및 배포 취소 할 때 발생하는 ServletContextListener를 사용할 수 있습니다.
public class MyServletContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent sce) { //application is being deployed } public void contextDestroyed(ServletContextEvent sce) { //application is being undeployed } }
Spring 컨텍스트를 가져 와서 Spring 빈에 접근 할 수있다.
public void contextDestroyed(ServletContextEvent sce) { ServletContext ctx = sce.getServletContext(); WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(ctx); //retrieve your Spring beans here... SomeSpringBean bean = (SomeSpringBean)ctx.getBean("someSprinbgBean"); //... }
-
==============================
3.Spring 3+를 사용하면 ContextCleanupListener를 애플리케이션 컨텍스트에 추가 할 수있다.
Spring 3+를 사용하면 ContextCleanupListener를 애플리케이션 컨텍스트에 추가 할 수있다.
그렇게 시작할 때 리스너를 등록하십시오 (xml config를 사용하는 것을 선호 할 수도 있지만 동일하게 적용됩니다)
package com.myapp import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextCleanupListener; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class MyWebApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { WebApplicationContext appContext = getContext(); servletContext.addListener(new ContextLoaderListener(appContext)); // line adding an implementation of ContextCleanupListener servletContext.addListener(new MyWebApplicationCleanupListener()); ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(appContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } private AnnotationConfigWebApplicationContext getContext() { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.setConfigLocation("com.myapp"); return context; } }
종료 코드를 실행하는 ContextCleanupListener 구현 :
package com.myapp; import javax.servlet.ServletContextEvent; import com.myapp.resources.requiring.clean.shutdown import org.springframework.web.context.ContextCleanupListener; public class MyWebApplicationCleanupListener extends ContextCleanupListener { @Override public void contextDestroyed(ServletContextEvent event) { // put your shutdown code in here MyResourceNeedingShutdown dataStore = MyResourceNeedingShutdown.getInstance(); dataStore.shutdown(); } }
예를 들어 tomcat을 실행하고 CTRL + C를 눌러 종료하면 즉시 중단 점을 넣으면 디버거에서 contextDestroyed 메서드가 실행되는 것을 볼 수 있습니다.
-
==============================
4.@Luiggi Mendoza 응답은 web.xml에 항목을 추가 할 때 작동하기 시작합니다.
@Luiggi Mendoza 응답은 web.xml에 항목을 추가 할 때 작동하기 시작합니다.
<web-app ...> <listener> <listener-class> com....MyServletContextListener </listener-class> </listener> </web-app>
당신은 tomcat에 의해 리스너 객체를 초기화 / 통지하는 스택 추적을 볼 수 있습니다; 봄이 오기 훨씬 전에.
com....MyServletContextListener.init(nothing but calling @PostConstruct) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.core.DefaultInstanceManager.postConstruct(DefaultInstanceManager.java:203) at org.apache.catalina.core.DefaultInstanceManager.postConstruct(DefaultInstanceManager.java:188) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:143) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:119) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4649) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5189) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:724) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:700) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:952) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1823) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)
그러나 중요한 것은 @PreDestroy가 Spring에 의해 먼저 호출 된 다음 contextDestroyed가 호출 된 후 @PreDestroy가 스프링이 아닌 스레드에 의해 호출 된 후에입니다.
그래서 당신이 어떤 일을 끝내고 싶다면; 그 시간에 다른 리소스 스레드를 사용할 수있게하려면이 @PreDestroy를 잡으십시오.
@PreDestroy public void cleanup() { eventTaskExecutor.shutdown(); try { /** * This is blocking call to avoid other threads (like logger demon thread) * not closed before this completes the job. Else worker thread cannot log * event. * * This will be the case when thread is busy in getting the web response, * better will wait for that, and log the web response. * */ eventTaskExecutor.awaitTermination(20, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } }
아래 내용은 클래스 내에서 @postConstruct 훅을 얻는 또 다른 방법이라는 것을 알아 두십시오.
@Autowired public void setApplicationContext(ApplicationContext applicationContext) { applicationContext.getBean("myRelatedClass", MyRelatedClass.class); }
한가지 더 @PreDestroy는 프로토 타입 객체에 사용할 수없는 싱글 톤 객체에만 호출됩니다.
from https://stackoverflow.com/questions/23936162/register-shutdownhook-in-web-application by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 보안 3.2 특정 URL에 대한 CSRF 비활성화 (0) | 2019.01.31 |
---|---|
[SPRING] 적절한 드라이버가 발견되지 않았습니다. (0) | 2019.01.31 |
[SPRING] 동일한 데이터베이스 테이블에 두 개의 JPA 또는 Hibernate 엔티티를 매핑하는 방법 (0) | 2019.01.30 |
[SPRING] classpath를 사용 : 봄 (0) | 2019.01.30 |
[SPRING] Spring Boot Application 클래스가 @Configuration annotation을 필요로하는 이유는 무엇입니까? (0) | 2019.01.30 |