ServletContainerInitializer与ServletContextListener

时间:2012-05-27 19:18:51

标签: servlets initialization

我正在尝试使用servletContainerInitializer注册一个servlet,但它似乎不起作用,也许这是我的代码(请仔细阅读),但我开始怀疑ServletContainerInitializer和{{3之间的区别因为以下代码在用作ServletContextListener时运行正常。

来自servlet 3.0规范:

  

4.4

     

配置方法(动态添加servlet):

     

...或onStartup实施的ServletContainerInitializer方法......

ServletContainerInitializer

package com.marmoush.javaexamples.nullhaus.servlet;

import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class MyInit implements ServletContainerInitializer {
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        System.out.println("hello");
        ServletRegistration reg = ctx.addServlet("q31","com.marmoush.javaexamples.nullhaus.servlet.Q31");
        reg.addMapping("/q31/*");
    }
}

我正在尝试自动注册的servlet:

package com.marmoush.javaexamples.nullhaus.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Q31 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("hello world");
    }
}

来自nullhaus java示例网站的原始代码“仅编辑了类名”也没有用!

package com.marmoush.javaexamples.nullhaus.servlet;

import java.util.Set;

import javax.servlet.Servlet;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class MyInit implements ServletContainerInitializer {
    public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException {
        try {
            Class klass = Class.forName("com.marmoush.javaexamples.nullhaus.servlet.Q31");
            Class<Q31> clazz = (Class<Q31>) klass;
            Servlet s = ctx.createServlet(clazz);
            ServletRegistration.Dynamic d = ctx.addServlet("q31", s);
            d.addMapping("/baz/*");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2 个答案:

答案 0 :(得分:46)

ServletContainerInitializer实现意图捆绑在一个JAR文件中,而该文件又被删除在webapp的/WEB-INF/lib中。 JAR文件本身应该有一个/META-INF/services/javax.servlet.ServletContainerInitializer文件,其中包含JAR中ServletContainerInitializer实现的FQN。请注意,此文件不应放在webapp中!

这允许webapp模块开发人员让他们的JAR文件挂钩webapp的启动和关闭周期。确实,他们也可以使用ServletContextListener @WebListener来实现此目的,但如果webapp自己的web.xml文件在metadata-complete="true"中设置了<web-app>属性,则无效{1}}这意味着webapp不应扫描JAR以获取注释(这样可以节省启动时间)。

ServletContainerInitializer您的特定情况中不起作用只能意味着您实际上并未开发模块JAR文件,而只是您自己的Web应用程序的一部分。在这种情况下,您ServletContainerInitializer 无用,而您应该使用ServletContextListener

@WebListener
public class Config implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        // Do stuff during server startup.
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        // Do stuff during server shutdown.
    }

}

另见:

答案 1 :(得分:5)

检查您是否已经配置了ServletContainerInitializer 。应该在文件中配置ServletContainerInitializer类名:

META-INF/services/javax.servlet.ServletContainerInitializer

该文件应仅包含类名。在您的情况下,对于Ex,它应该如下所示:

com.marmoush.javaexamples.nullhaus.servlet.MyInit

文件( META-INF / services / javax.servlet.ServletContainerInitializer )可以捆绑在WEB-INF / lib中的库JAR中。

以下是解释的任何example