Servlet 3.0ではServletやFilter、およびそれらのURLマッピングをプログラムから動的に登録し、Webアプリケーションを拡張できます。拡張メソッドは、そのアプリケーションの初期化中でのみ、呼び出すことが可能です。
そのため、ServletContextListenerのcontexInitializedメソッドか、ServletContainerInitializerのonStartupメソッドのいずれかのみで利用できます。
利用可能なAPIの一部を紹介します。これらAPIはServletContextから呼び出せます。
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
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)
public <T extends Filter> T createFilter(Class<T> c) throws ServletException
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)
public <T extends EventListener> T createListener(Class<T> c) throws ServletException
public void addListener(Class<? extends EventListener> listenerClass)
public void addListener(String className)
addServletメソッドやaddFilterメソッドはServletRegistration.DynamicやFilterRegistration.Dynamicを返却します。開発者は、これらRegistrationインターフェイスを利用してServletやFilterのマッピングや初期パラメータの追加などを行います。
ServletRegistration.DynamicインターフェイスとFilterRegistration.DynamicインターフェイスのAPIの一部を、以下に記載します。
public Set<String> addMapping(String... urlPatterns)
public void setLoadOnStartup(int loadOnStartup)
public boolean setInitParameter(String name, String value)
public void setAsyncSupported(boolean isAsyncSupported)
public void addMappingForServletNames(
EnumSet<DispatcherType> dispatcherTypes,
boolean isMatchAfter, String... servletNames)
addMappingForUrlPatterns(
EnumSet<DispatcherType> dispatcherTypes,
boolean isMatchAfter, String... urlPatterns)
public boolean setInitParameter(String name, String value)
public void setAsyncSupported(boolean isAsyncSupported)
ServletContextListenerでの利用例は、こんな感じです。
@WebListener()
public class RegistServletContextListener implements
ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
// TODO
}
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext context = event.getServletContext();
Servlet servlet = null;
try {
servlet = context.createServlet(TestServlet.class);//---[1]
} catch (ServletException e) {
// TODO
}
ServletRegistration reg = context.addServlet("config", servlet);//---[2]
if (reg != null) {
Set conflicts = reg.addMapping("/config1");//---[3]
if (!conflicts.isEmpty()) {
// TODO
}
}
}
}
上記サンプルでは、[1]でTestServletクラスのインスタンスを生成し、【2]でコンテキストにTestServletインスタンスを登録します。
[3]で返却されたServletRegistrationに「/config1」をマッピングすることで、TestServletが/config1のパスでアクセスできるようになります。
もう1つ、ServletContainerInitializerでの利用例も載せておきます。
※ServletContainerInitializerはServlet 3.0から追加されたインターフェイスで、アプリケーションの初期化時にサービスプロバイダによって呼び出されます。
まず、JARのサービスプロバイダにServletContainerInitializerを登録します。
META-INF/services/javax.servlet.ServletContainerInitializer
ServletContainerInitializerを実装します。
public class TestInitializer implements ServletContainerInitializer {
@Override
public void onStartup(Set<Class<?>> classes, ServletContext ctxt)
throws ServletException {
ServletRegistration reg = ctxt.addServlet("initialTest", "init.TestServlet");
if (reg != null) {
Set conflicts = reg.addMapping("/testpath1", "/testpath2");
if (!conflicts.isEmpty()) {
// TODO
}
}
}
}
これら拡張メソッドを利用することで、Webコンテキスト初期化時にプログラムによって動的にWebアプリケーションを拡張できます。
Servlet 3.0では、JSPのモジュール化が追加されました。JARファイルの「META-INF/resources」配下に静的コンテンツやJSPを作成し、Webアプリケーションの「WEB-INF/lib」にJARを配置することで、それらのファイルにWebからアクセスできます。
JSPを1つのJARに固めて利用できるので、ちょっと便利です。
今回はTomcat 7の紹介としてServlet 3.0のうち、EoDとモジュール化と拡張性を紹介しました。
次回は、Servlet 3.0の変更点の紹介の続きとして、非同期処理、セキュリティ、Session Tracking、マルチパート対応について紹介する予定です。
Copyright © ITmedia, Inc. All Rights Reserved.