问题描述
我正在尝试使用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
:
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文件中,然后将其放入Webapp的/WEB-INF/lib
中. JAR文件本身应具有一个/META-INF/services/javax.servlet.ServletContainerInitializer
文件,其中应包含JAR中ServletContainerInitializer
实现的FQN.请注意,因此不应将此文件放置在webapp本身中!
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的启动和关闭周期上.的确,他们也可以将ServletContextListener
与@WebListener
一起使用,但是如果webapp自己的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文件,而只是您自己的Web应用程序不可或缺的一部分.在这种情况下,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.
}
}
另请参见:
- 以编程方式而不是使用Web来映射servlet. xml或注释
- 将共享代码和web.xml从WAR项目拆分为通用JAR项目
- 使用特殊的自动启动servlet在启动时初始化并共享应用程序数据
- 什么是ServletContainerInitializer中的contextDestroyed()等效项? /a>
- Map servlet programmatically instead of using web.xml or annotations
- Splitting up shared code and web.xml from WAR project to common JAR project
- Using special auto start servlet to initialize on startup and share application data
- what is the equivalence of contextDestroyed() in ServletContainerInitializer?
See also:
这篇关于ServletContainerInitializer与ServletContextListener的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!