40

我正在尝试使用 servletContainerInitializer 注册一个 servlet,但它似乎不起作用,也许这是我的代码(请查看它),但我开始想知道 and 之间的区别,ServletContainerInitializer因为ServletContextListener以下代码在用作时运行良好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();
        }
    }
}
4

2 回答 2

51

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

这允许 webapp 模块开发人员让他们的 JAR 文件挂钩 webapp 的启动和关闭周期。确实,他们也可以为此使用ServletContextListenerwith @WebListener,但是如果 webapp 自己的web.xml文件metadata-complete="true"设置了一个属性,<web-app>这意味着 webapp 不应该扫描 JAR 中的注释(这可以节省启动时间),这将不起作用。

您的特定情况下ServletContainerInitializer不起作用只能意味着您实际上没有开发模块 JAR 文件,而只是您自己的 Web 应用程序不可或缺的一部分。在这种情况下,对你来说没用,你应该改用。ServletContainerInitializerServletContextListener

@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.
    }

}

也可以看看:

于 2012-05-28T12:30:12.173 回答
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 中。

这是任何解释的例子

于 2012-05-28T11:27:55.957 回答