只能在webapp启动时进行注册.
在Servlet3.0中可以动态注册Servlet,Filter,Listener,在ServletContext对应注册API为:
/**
* 添加Servlet
*/
public ServletRegistration.Dynamic addServlet(String servletName,
String className);
public ServletRegistration.Dynamic addServlet(String servletName,
Servlet servlet);
public ServletRegistration.Dynamic addServlet(String servletName,
Class<? extends Servlet> servletClass);
/**
* 添加Filter
*/
public FilterRegistration.Dynamic addFilter(String filterName,
String className);
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter);
public FilterRegistration.Dynamic addFilter(String filterName,
Class<? extends Filter> filterClass);
/**
* 添加Listener
*/
public void addListener(String className);
public <T extends EventListener> void addListener(T t);
public void addListener(Class<? extends EventListener> listenerClass);每个组件注册都提供三个方法。
只能在初始化时进行注册。在初始化情况下的注册Servlet组件有两种方法:
1.实现ServletContextListener接口,在contextInitialized方法中完成注册.
2.在jar文件中放实现ServletContainerInitializer接口的初始化器
在ServletContextListener监听器中完成注册。
public void contextInitialized(ServletContextEvent sce) {
ServletContext sc = sce.getServletContext();
// Register Servlet
ServletRegistration sr = sc.addServlet("DynamicServlet",
"web.servlet.dynamicregistration_war.TestServlet");
sr.setInitParameter("servletInitName", "servletInitValue");
sr.addMapping("/*");
// Register Filter
FilterRegistration fr = sc.addFilter("DynamicFilter",
"web.servlet.dynamicregistration_war.TestFilter");
fr.setInitParameter("filterInitName", "filterInitValue");
fr.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST),
true, "DynamicServlet");
// Register ServletRequestListener
sc.addListener("web.servlet.dynamicregistration_war.TestServletRequestListener");
}在jar文件中的servlet组件注册,需要在jar包含META-INF/services/javax.servlet.ServletContainerInitializer文件,文件内容为已经实现ServletContainerInitializer接口的类:
com.learn.servlet3.jardync.CustomServletContainerInitializer该实现部分代码:
@HandlesTypes({ JarWelcomeServlet.class })
public class CustomServletContainerInitializer implements
ServletContainerInitializer {
private static final Log log = LogFactory
.getLog(CustomServletContainerInitializer.class);
private static final String JAR_HELLO_URL = "/jarhello";
public void onStartup(Set<Class<?>> c, ServletContext servletContext)
throws ServletException {
log.info("CustomServletContainerInitializer is loaded here...");
log.info("now ready to add servlet : " + JarWelcomeServlet.class.getName());
ServletRegistration.Dynamic servlet = servletContext.addServlet(
JarWelcomeServlet.class.getSimpleName(),
JarWelcomeServlet.class);
servlet.addMapping(JAR_HELLO_URL);
log.info("now ready to add filter : " + JarWelcomeFilter.class.getName());
FilterRegistration.Dynamic filter = servletContext.addFilter(
JarWelcomeFilter.class.getSimpleName(), JarWelcomeFilter.class);
EnumSet<DispatcherType> dispatcherTypes = EnumSet
.allOf(DispatcherType.class);
dispatcherTypes.add(DispatcherType.REQUEST);
dispatcherTypes.add(DispatcherType.FORWARD);
filter.addMappingForUrlPatterns(dispatcherTypes, true, JAR_HELLO_URL);
log.info("now ready to add listener : " + JarWelcomeListener.class.getName());
servletContext.addListener(JarWelcomeListener.class);
}
}其中@HandlesTypes注解表示CustomServletContainerInitializer 可以处理的类,在onStartup 方法中,可以通过Set<Class<?>> c 获取得到。
jar文件中不但可以包含需要自定义注册的servlet,也可以包含应用注解的servlet,具体怎么做,视具体环境而定。
把处理某类事物的servlet组件打包成jar文件,有利于部署和传输,功能不要了,直接去除掉jar即可,方便至极!