ServletContainerInitializer

ServletContainerInitializer

本文介绍了ServletContainerInitializer 与 ServletContextListener的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 servletContainerInitializer 注册一个 servlet,但它似乎不起作用,也许这是我的代码(请检查它),但我开始想知道 ServletContainerInitializerServletContextListener,因为以下代码在用作 ServletContextListener 时运行良好 代替.

I'm trying to register a servlet using servletContainerInitializer but it doesn't seem to work, Maybe it's my code (kindly review it), but I came to wonder about the difference between ServletContainerInitializer and ServletContextListener, because the follwing code runs fine when used as ServletContextListener instead.

来自 servlet 3.0 规范:

From servlet 3.0 specification:

... 或来自 ServletContainerInitializer 实现的 onStartup 方法...

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:

The servlet which I'm trying to auto-register:

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 示例网站的原始代码仅编辑了类名";也没有用!

Original code from nullhaus java examples website "only class name edited" also didn't work!

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();
        }
    }
}

推荐答案

ServletContainerInitializer 实现旨在捆绑在 JAR 文件中,而 JAR 文件又被放入 /WEB-INF/lib 的 web 应用程序.JAR 文件本身应该有一个 /META-INF/services/javax.servlet.ServletContainerInitializer 文件,其中包含 JAR 中 ServletContainerInitializer 实现的 FQN.请注意,因此不应将此文件放在 web 应用程序本身中!

The ServletContainerInitializer implementation is intented to be bundled in a JAR file which is in turn been dropped in /WEB-INF/lib of the webapp. The JAR file itself should have a /META-INF/services/javax.servlet.ServletContainerInitializer file containing the FQN of the ServletContainerInitializer implementation in the JAR. Please note that this file should thus not be placed in the webapp itself!

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

This allows webapp module developers to let their JAR file hook on webapp's startup and shutdown cycle. It's true that they could also have used a ServletContextListener with @WebListener for this, but this won't work if the webapp's own web.xml file has a metadata-complete="true" attribute set in <web-app> which means that the webapp shouldn't scan JARs for annotations (which saves startup time).

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

That the ServletContainerInitializer doesn't work in your particular case can only mean that you're actually not developing a module JAR file, but just a part integral to your own web application. In that case, the ServletContainerInitializer is useless for you and you should be using ServletContextListener instead.

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

}

另见:

07-11 11:02