问题描述
我正在尝试使用 servletContainerInitializer 注册一个 servlet,但它似乎不起作用,也许这是我的代码(请检查它),但我开始想知道 ServletContainerInitializer
和 ServletContextListener
,因为以下代码在用作 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 的启动和关闭周期.确实,他们也可以为此使用带有 @WebListener
的 ServletContextListener
,但是如果 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.
}
}
另见:
- 以编程方式映射 servlet,而不是使用 Web.xml 或注解
- 将共享代码和 web.xml 从 WAR 项目拆分为公共 JAR 项目
- 使用特殊的自动启动servlet 在启动时初始化并共享应用程序数据
- ServletContainerInitializer 中 contextDestroyed() 的等价性是什么?
这篇关于ServletContainerInitializer 与 ServletContextListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!