Servlets 未调用ServletContextListener

Servlets 未调用ServletContextListener,servlets,servlet-listeners,Servlets,Servlet Listeners,我使用EclipseMaven插件创建了一个JavaEE7项目。我的问题是,当我运行应用程序时,没有调用实现SerlvetContextListener的类。是什么导致了这个问题 @WebListener public class ApplicationContextListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent sc

我使用EclipseMaven插件创建了一个JavaEE7项目。我的问题是,当我运行应用程序时,没有调用实现SerlvetContextListener的类。是什么导致了这个问题

@WebListener
public class ApplicationContextListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce)
    {
        Request request = new HttpRequest(sce);
        new Thread (request).start();
        HibernateUtil.getSessionFactory();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) 
    {

    }

}
web.xml:


com.kyrogaming.AppServletContextListener
泽西servlet
com.sun.jersey.spi.container.servlet.ServletContainer
com.sun.jersey.config.property.packages
com.kyrogaming.webservices
泽西servlet
/服务/*
index.html

在web.xml中,还需要指定


com.kyrogaming.AppServletContextListener
在web.xml中使用metadata complete=“false”修复了这个问题

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="false">

总结JNL和Ted Goddard的答案:

对于要由servlet容器加载的ServletContextListener(或其他侦听器,如ServletContextAttributeListener或ServletRequestAttributeListener),您需要告诉容器有关它的信息。因此,有三种方法可以做到这一点:

  • 在部署描述符(web.xml)中声明它:

    com.kyrogaming.AppServletContextListener
  • 或使用注释对其类进行注释(请参见下面的“注释注释”)

  • 或者通过ServletContext中的方法以编程方式注册它,例如

  • 注释说明

    方法1)和3)始终有效。要使方法2(注释)起作用,必须将servlet容器配置为扫描类路径中的类,以找到带注释的侦听器类

    如果WEB.xml包含属性
    metadata complete=“true”
    (该属性默认为
    false
    ),则不会扫描webapp自己的类(在
    WEB-INF/classes
    下)和库(在
    WEB-INF/lib
    下的JAR)。参见第8.1章“注释和可插拔性”

    在web应用程序中,只有当使用注释的类位于web-INF/classes目录中,或者如果它们打包在应用程序中web-INF/lib中的jar文件中,才会对它们的注释进行处理。web应用程序部署描述符在web app元素上包含一个新的“metadata complete”属性。“metadata complete”属性定义web描述符是否完整,或者在部署时是否应检查jar文件的类文件中的注释和web片段。如果“metadata complete”设置为“true”,则部署工具必须忽略应用程序和web片段的类文件中存在的任何servlet注释。如果未指定metadata complete属性或将其设置为“false”,则部署工具必须检查应用程序的类文件中的注释,并扫描web片段

    因此,要允许容器在JAR中查找带注释的类,请确保web.xml设置了
    metadata complete=“false”
    ,或者根本不设置它

    请注意,设置此选项可能会延迟应用程序启动;例如,见



    不幸的是,这仍然不能解释为什么问题中的ServletContextListener没有加载。请注意,问题中的web.xml没有
    元数据完成
    ,这意味着它默认为
    false
    ,因此启用了类路径扫描。可能还有其他一些问题;希望这个清单有助于找到它。

    为了记录在案,我添加了另一个导致
    ServletContextListener
    未被调用的可能原因(而且相当恶性)

    当您有
    java.lang.LinkageError
    时,即忘记将
    提供的
    添加到
    javax.servlet api
    依赖项时,可能会发生这种情况。 在这种情况下,将创建侦听器实例,但只执行静态部分,而不执行
    contextInitialized
    contextdestromed
    方法


    只有在调用某个servlet时才能发现,因为在侦听器实例化期间不会引发链接错误。

    正在运行的容器可能需要显式允许扫描注释:

    码头交货价:

    cd [JETTY_BASE]
    java -jar [JETTY_HOME]/start.jar --add-module=annotations
    

    还有一种极为罕见的情况会导致这种情况。(我花了4个小时才揭开)

    如果您使用的是Tomcat10,那么就不能在maven/gradle中使用
    javax.servlet

    Tomcat9仍然有
    javax.servlet
    ,但Tomcat10迁移到
    jakarta.servlet

    Tomcat10希望有一个使用
    jakarta.servlet.ServletContextListener

    所以使用这个maven依赖项:(提供了作用域,因为Tomcat10已经有了这样的库)

    
    jakarta.servlet
    jakarta.servlet-api
    5.0.0
    假如
    
    这是不真实的。由于JavaEE6,您可以使用
    @WebListener
    注册它们,而不需要任何
    web.xml
    条目。请及时跟进,JavaEE6已经在2009年12月发布了。这也适用于错误地将这个错误答案投上高分的人。根据目前提供的信息,这个问题不可回答。如果我猜的话,那么该侦听器实际上从未在运行时类路径中结束。
    cd [JETTY_BASE]
    java -jar [JETTY_HOME]/start.jar --add-module=annotations
    
            <dependency>
                <groupId>jakarta.servlet</groupId>
                <artifactId>jakarta.servlet-api</artifactId>
                <version>5.0.0</version>
                <scope>provided</scope>
            </dependency>