Java 在web应用程序中注册shutDownHook
我们如何在web应用程序中注册下拉钩子 在web.xml或applicationContext.xml中注册它有什么方法吗 我知道,如果我们将应用程序与主类一起使用,它很简单Java 在web应用程序中注册shutDownHook,java,spring,tomcat,web,ioc-container,Java,Spring,Tomcat,Web,Ioc Container,我们如何在web应用程序中注册下拉钩子 在web.xml或applicationContext.xml中注册它有什么方法吗 我知道,如果我们将应用程序与主类一起使用,它很简单 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); context.registerShutdownHook(); 但是web应用程序呢?由于它在web应用程序
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
context.registerShutdownHook();
但是web应用程序呢?由于它在web应用程序中使用ContextListener,您可以使用在部署和取消部署应用程序时触发的:
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 bean:
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");
//...
}
独立(非web)应用程序中的RegisterShotDownhook():
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();
}
}
@PreDestroy
注释用于bean方法,以便在从上下文中删除bean或上下文关闭时收到通知
当调用context.close()
或context.registerShutdownHook()
时,将触发关闭事件
@Component(value="someBean")
public class SomeBean {
@PreDestroy
public void destroy() {
System.out.println("Im inside destroy...");
}
}
我希望你已经知道了
web应用程序中的RegisterShotDownhook():
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();
}
}
在web应用程序中,DispatcherServlet/ContextListener创建ApplicationContext,并在服务器关闭时关闭上下文。不需要显式调用context.close()
或context.registerShutdownHook()
当服务器关闭时,bean上的
@PreDestory
方法将被自动通知。使用Spring 3+可以向应用程序上下文添加ContextCleanupListener
这样在启动时注册侦听器(您可能更喜欢使用xml配置,但同样适用)
运行关闭代码的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方法被命中 @Luiggi Mendoza在我在web.xml中添加条目时,答案开始工作
<web-app ...>
<listener>
<listener-class>
com....MyServletContextListener
</listener-class>
</listener>
</web-app>
但重要的是首先由Spring调用@PreDestroy,然后在contextdestroy调用之后,再由非Spring线程调用@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只对单例对象调用,而对原型对象不可用。谢谢您的回答。你们能告诉我,我怎样才能得到代表SPRING上下文的对象吗。我可以在其上调用context.registerShutdownHook()@Javakid如果您了解bean作为原型会发生什么,我不需要给出解释:流程将根据从上下文中删除的实例进行调用。人们不使用
prototype
(正确与否),主要是因为bean的默认范围是singleton
。由于OP没有提供流程的行为方式或任何场景,因此这可能是最好的选择。可能清理过程需要几个bean和它们的编排。@Javakid在维护遗留应用程序,特别是非常旧的应用程序时,没有关注点分离定律(只需看看应用程序具有的单片体系结构),因此这是可用的选项。在这里,我唯一确信的是,如果您希望在普通web应用程序中的某个特定位置启动任何清理过程,那么这是最安全的方法。我的回答中没有涉及特定于框架的好处(或者说是你自己毁灭的后门),对于这种情况,最好了解@PreDestruct
。请注意,@PreDestruct
不是来自Spring,而是来自JavaEE。谢谢您的建议。但这种方法不起作用。我添加了必要的函数@Override public void contextInitialized(ServletContextSce){ServletContext=sce.getServletContext();WebApplicationContext springContext=WebApplicationContextILS.getWebApplicationContext(context);ClassPathXmlApplicationContext applicationContext=(ClassPathXmlApplicationContext)springContext.getParent();applicationContext.RegisterShotdownhook();}但是当我调用applicationContext.RegisterShotdownhook()时1.我有空指针excaption@KanagaveluSugumarSpring会为您连接所有东西。如果某些东西无法连接是因为延迟连接或无法创建bean,您必须检查为什么没有创建。响应非常好。@PreDestroy是关键!非常感谢:-)@Kalyan::@PreDestroy被要求销毁bean,这意味着,如果bean不是单例的,那么每当容器删除bean时,就会多次调用它。@Anandj.Kadhi这不是真的-您有什么解决方案吗?