我正在使用NetBeans和Tomcat似乎在.war应用程序中部署了两次,这是Web应用程序的双重启动 .
我已经尝试了Tomcat 6和7以及相同的结果 .
我有一个Spring MVC,Hibernate和Thymeleaf应用程序 . META-INF下的Context.xml具有以下内容:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/website"/>
这是日志 .
**First deployment starts**
[ INFO] 07:13:09 ContextLoader - Root WebApplicationContext: initialization started
[ INFO] 07:13:09 XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu May 23 07:13:09 EST 2013]; root of context hierarchy
2013-05-23 07:13:10 JRebel: Monitoring Spring bean definitions in '/Users/pack/NetBeansProjects/mysite/site/src/main/webapp/WEB-INF/applicationContext- data.xml'.
[ INFO] 07:13:10 XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext-data.xml]
[ INFO] 07:13:10 ClassPathScanningCandidateComponentProvider - JSR-330 'javax.inject.Named' annotation found and supported for component scanning
***(tomcat initializes hibernate and other spring beans)***
...
May 23, 2013 7:13:17 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 15552 ms
***Tomcat started***
***Tomcat tries to shut down the context***
[ INFO] 07:13:18 XmlWebApplicationContext - Closing WebApplicationContext for namespace 'spring-mvc-servlet': startup date [Thu May 23 07:13:15 EST 2013]; parent: Root WebApplicationContext
[ INFO] 07:13:18 DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5bbe2de2: defining beans [blHeadProcessor,blHeadProcessorExtensionManager,navigationProcessor,blPaginationPageLinkPro cessor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,blRegisterCustomerValidator,blCategoryController,com.package.ui.thymeleaf.CategoryHandlerMapping#0,templateResolver,templateEngine,org.thymeleaf.spring3.view.ThymeleafViewResolver#0,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@521e7f21
[ INFO] 07:13:18 XmlWebApplicationContext - Closing Root WebApplicationContext: startup date [Thu May 23 07:13:09 EST 2013]; root of context hierarchy
[ INFO] 07:13:18 DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@521e7f21: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,blCategoryDao,blCustomerDao,blIdGenerationDao,nlpDao,jpaTemplate,webDS,entityManagerFactory,transactionManager,org.springframework.security.filterChains,org.springframework.security.filterChainProxy,org.springframework.security.web.DefaultSecurityFilterChain#0,org.springframework.security.web.DefaultSecurityFilterChain#1,org.springframework.security.web.DefaultSecurityFilterChain#2,org.springframework.security.web.DefaultSecurityFilterChain#3,org.springframework.security.web.DefaultSecurityFilterChain#4,org.springframework.security.web.DefaultSecurityFilterChain#5,org.springframework.security.web.PortMapperImpl#0,org.springframework.security.web.PortResolverImpl#0,org.springframework.security.authentication.ProviderManager#0,org.springframework.security.web.context.HttpSessionSecurityContextRepository#0,org.springframework.security.web.savedrequest.HttpSessionRequestCache#0,org.springframework.security.web.access.channel.ChannelDecisionManagerImpl#0,org.springframework.security.access.vote.AffirmativeBased#0,org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0,org.springframework.security.web.access.DefaultWebInvocationPrivilegeEvaluator#0,org.springframework.security.authentication.AnonymousAuthenticationProvider#0,org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter#0,org.springframework.security.userDetailsServiceFactory,org.springframework.security.web.DefaultSecurityFilterChain#6,org.springframework.security.authentication.dao.DaoAuthenticationProvider#0,org.springframework.security.authentication.DefaultAuthenticationEventPublisher#0,org.springframework.security.authenticationManager,blUserDetailsService,blCatalogService,blCustomerService,entityService,fbPageService,blIdGenerationService,blLoginService,nlpService,priceIncreaseValidator,searchFacetService,blEntityConfiguration,blPasswordEncoder,solrIndexService,solrEmbedded,textEncryptor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
[ INFO] 07:13:18 LocalContainerEntityManagerFactoryBean - Closing JPA EntityManagerFactory for persistence unit 'blPU'
[ INFO] 07:13:18 SessionFactoryImpl - closing
May 23, 2013 7:13:18 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [/website] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
May 23, 2013 7:13:19 AM org.apache.catalina.startup.HostConfig deleteRedeployResources
INFO: Undeploying context [/website]
May 23, 2013 7:13:19 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor /Users/pack/Servers/apache-tomcat- 7.0.34/conf/Catalina/localhost/website.xml
2013-05-23 07:13:23 JRebel: Monitoring Log4j configuration in 'file:/Users/pack/NetBeansProjects/mysite/site/target/mycompany/WEB-INF/classes/log4j.xml'.
***Tomcat tries to restart again***
[ INFO] 07:13:23 ContextLoader - Root WebApplicationContext: initialization started
[ INFO] 07:13:23 XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu May 23 07:13:23 EST 2013]; root of context hierarchy
2013-05-23 07:13:24 JRebel: Monitoring Spring bean definitions in '/Users/pack/NetBeansProjects/mysite/site/src/main/webapp/WEB-INF/applicationContext- data.xml'.
[ INFO] 07:13:24 XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext-data.xml]
它成功启动 .
我不明白的是Tomcat为什么要两次部署应用程序 . 第一次在新的tomcat实例上部署应用程序时不会发生这种情况,因为website.xml文件尚未位于tomcats / conf / catalina / localhost文件夹中 . 但是当我再次从netbeans停止并运行tomcat时,website.xml文件仍然在/ conf / catalina / localhost文件夹中,但在第二次部署即将发生之前就被删除并重新部署 .
我已经尝试将Tomcat的server.xml文件中的 autoDeploy
设置为false但它没有帮助 .
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="false">
可能是每次tomcat停止时,Tomcat应该删除/ conf / catalina / localhost文件夹下的website.xml文件 .
这就是localhost文件夹下的website.xml文件的样子
<?xml version="1.0" encoding="UTF-8"?>
<Context
docBase="/Users/pack/NetBeansProjects/mysite/site/target/mycompany"
path="/website"
/>
3 回答
我发现删除文件conf / localhost / myappname.xml会阻止应用程序初始化两次 . 基本上Tomcat正在重新启动,并重新启动旧版本的应用程序 . 然后当Netbeans部署它时它再次启动 . 作为一种解决方法,我在ContextListener contextDestroyed()事件中添加了几行代码:
在web.xml中,在开发环境中添加以下内容:
然后,下次部署应用程序时,它将不会在部署之前再次启动,因此不会启动两次 . 在部署或关闭之前删除文件的任何其他想法将不胜感激 .
感谢the answer by epoch和answer by Steven Neiner .
这是我的代码版本 . 我的分歧:
标记方法为
synchronized
.理论上不需要,但鉴于我们在这里处理奇怪的多重发射问题,最好是安全而不是抱歉 .
替换了对第三方实用程序的调用(Spring?) .
通过查找
catalina.base
路径中的某些措辞来检测是否在开发中运行 .删除了
static
修饰符 . 使用作为枚举实现的单例 .截至2016-05,重写代码以便于阅读和理解(至少对我而言) . 仅进行了简单测试,因此请务必在使用前查看源代码(必须完全使用,风险自负) .
概念
他们解决此错误的核心是删除以您的Web应用程序名称命名的文件(您的“servlet上下文”)并附加
.xml
.例如,如果您的Web应用程序名为
AcmeApp
,请找到并删除名为AcmeApp.xml
的文件 . 此文件存储在“Catalina base”文件夹中 .将此删除作为Web应用程序运行的最后一步 . 因此,当Web应用程序再次启动时,该文件将不存在,并将重新创建 . 请记住,这只是在开发模式下 . 在 生产环境 中单独使用Tomcat时不会发生错误 .
那么我们如何运行此变通方法代码作为我们的Web应用程序执行的最后一个行为?继续阅读 .
如何使用
作为版本2.3及更高版本Servlet spec的标准部分,每个Servlet container都可以在您的网络启动时调用您的代码,并在您的Web应用程序关闭时再次调用 . 这不是Tomcat特有的; Jetty,GlassFish,WildFly/JBoss等等,都包含Servlet规范要求的此功能 .
要使用上面显示的代码,请在项目中添加一个新类 . 将新类命名为"MyServletContextListener.java" . 将该类声明为实现ServletContextListener接口 .
实现此接口所需的两种方法 . 当您的Web应用程序启动时,您的Servlet容器(Tomcat)会调用一种方法,保证在第一个用户访问您的应用程序之前运行 . 当您的Web应用程序被Servlet容器(Tomcat)关闭时,将调用另一个方法 .
在
contextDestroyed
方法中,调用上面显示的方法 . 像这样:配置很简单 . 仅仅将这个类与你的servlet类一起包含在一起WAR file/folder . @WebListener注释使Servlet容器“注意”此侦听器类,加载并实例化它,并在适当时执行其每个方法 . 如果需要,您可以使用备用配置模式而不是注释,但注释是最简单的路径 .
这是一个整个AppListener类作为完整示例 . 我重写了以前发布的此代码版本,以便于阅读和理解 .
这里是帮助程序类,用于确定是否在开发模式下运行 . 阅读评论以获得更多讨论 . 结果是在开发时似乎没有简单的干净方法来检测,无法检测何时从NetBeans运行Tomcat而不是自己运行Tomcat . I have asked但尚未收到任何更好的解决方案 .
CAVEAT: 您必须更改此
isInDevelopmentMode
方法以匹配您的特定开发环境 .首先,谢谢史蒂文!这是一个更便携的修复版本:
PS:用你自己的版本替换未知的引用:)
从ServletContextListener实现的contextDestroyed方法中调用此自定义方法 .