Package org.springframework.web

Source Code of org.springframework.web.SpringServletContainerInitializer

/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.web;

import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;

import org.springframework.core.annotation.AnnotationAwareOrderComparator;

/**
* Servlet 3.0 {@link ServletContainerInitializer} designed to support code-based
* configuration of the servlet container using Spring's {@link WebApplicationInitializer}
* SPI as opposed to (or possibly in combination with) the traditional
* {@code web.xml}-based approach.
*
* <h2>Mechanism of Operation</h2>
* This class will be loaded and instantiated and have its {@link #onStartup}
* method invoked by any Servlet 3.0-compliant container during container startup assuming
* that the {@code spring-web} module JAR is present on the classpath. This occurs through
* the JAR Services API {@link ServiceLoader#load(Class)} method detecting the
* {@code spring-web} module's {@code META-INF/services/javax.servlet.ServletContainerInitializer}
* service provider configuration file. See the
* <a href="http://download.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider">
* JAR Services API documentation</a> as well as section <em>8.2.4</em> of the Servlet 3.0
* Final Draft specification for complete details.
*
* <h3>In combination with {@code web.xml}</h3>
* <p>If a web application includes a {@code WEB-INF/web.xml} file, it is important to
* understand that neither this nor any other {@code ServletContextInitializer} will be
* processed unless the {@code <web-app>} element's {@code version} attribute is >= "3.0"
* and the {@code xsi:schemaLocation} for "http://java.sun.com/xml/ns/javaee" is set to
* "http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd".
* <p>A web application can choose to limit the amount of classpath scanning the Servlet
* container does at startup either through the {@code metadata-complete} attribute in
* {@code web.xml}, which controls scanning for Servlet annotations or through an
* {@code <absolute-ordering>} element also in {@code web.xml}, which controls which
* web fragments (i.e. jars) are allowed to perform a {@code ServletContainerInitializer}
* scan. When using this feature, the {@link SpringServletContainerInitializer}
* can be enabled by adding "spring_web" to the list of named web fragments in
* {@code web.xml} as follows:
*
* <pre class="code">
* {@code
* <absolute-ordering>
*   <name>some_web_fragment</name>
*   <name>spring_web</name>
* </absolute-ordering>
* }</pre>
*
* <h2>Relationship to Spring's {@code WebApplicationInitializer}</h2>
* Spring's {@code WebApplicationInitializer} SPI consists of just one method:
* {@link WebApplicationInitializer#onStartup(ServletContext)}. The signature is intentionally
* quite similar to {@link ServletContainerInitializer#onStartup(Set, ServletContext)}:
* simply put, {@code SpringServletContainerInitializer} is responsible for instantiating
* and delegating the {@code ServletContext} to any user-defined
* {@code WebApplicationInitializer} implementations. It is then the responsibility of
* each {@code WebApplicationInitializer} to do the actual work of initializing the
* {@code ServletContext}. The exact process of delegation is described in detail in the
* {@link #onStartup onStartup} documentation below.
*
* <h2>General Notes</h2>
* In general, this class should be viewed as <em>supporting infrastructure</em> for
* the more important and user-facing {@code WebApplicationInitializer} SPI. Taking
* advantage of this container initializer is also completely <em>optional</em>: while
* it is true that this initializer will be loaded and invoked under all Servlet 3.0+
* runtimes, it remains the user's choice whether to make any
* {@code WebApplicationInitializer} implementations available on the classpath. If no
* {@code WebApplicationInitializer} types are detected, this container initializer will
* have no effect.
*
* <p>Note that use of this container initializer and of {@code WebApplicationInitializer}
* is not in any way "tied" to Spring MVC other than the fact that the types are shipped
* in the {@code spring-web} module JAR. Rather, they can be considered general-purpose
* in their ability to facilitate convenient code-based configuration of the
* {@code ServletContext}. In other words, any servlet, listener, or filter may be
* registered within a {@code WebApplicationInitializer}, not just Spring MVC-specific
* components.
*
* <p>This class is neither designed for extension nor intended to be extended.
* It should be considered an internal type, with {@code WebApplicationInitializer}
* being the public-facing SPI.
*
* <h2>See Also</h2>
* See {@link WebApplicationInitializer} Javadoc for examples and detailed usage
* recommendations.<p>
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Rossen Stoyanchev
* @since 3.1
* @see #onStartup(Set, ServletContext)
* @see WebApplicationInitializer
*/
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {

  /**
   * Delegate the {@code ServletContext} to any {@link WebApplicationInitializer}
   * implementations present on the application classpath.
   *
   * <p>Because this class declares @{@code HandlesTypes(WebApplicationInitializer.class)},
   * Servlet 3.0+ containers will automatically scan the classpath for implementations
   * of Spring's {@code WebApplicationInitializer} interface and provide the set of all
   * such types to the {@code webAppInitializerClasses} parameter of this method.
   *
   * <p>If no {@code WebApplicationInitializer} implementations are found on the
   * classpath, this method is effectively a no-op. An INFO-level log message will be
   * issued notifying the user that the {@code ServletContainerInitializer} has indeed
   * been invoked but that no {@code WebApplicationInitializer} implementations were
   * found.
   *
   * <p>Assuming that one or more {@code WebApplicationInitializer} types are detected,
   * they will be instantiated (and <em>sorted</em> if the @{@link
   * org.springframework.core.annotation.Order @Order} annotation is present or
   * the {@link org.springframework.core.Ordered Ordered} interface has been
   * implemented). Then the {@link WebApplicationInitializer#onStartup(ServletContext)}
   * method will be invoked on each instance, delegating the {@code ServletContext} such
   * that each instance may register and configure servlets such as Spring's
   * {@code DispatcherServlet}, listeners such as Spring's {@code ContextLoaderListener},
   * or any other Servlet API componentry such as filters.
   *
   * @param webAppInitializerClasses all implementations of
   * {@link WebApplicationInitializer} found on the application classpath
   * @param servletContext the servlet context to be initialized
   * @see WebApplicationInitializer#onStartup(ServletContext)
   * @see AnnotationAwareOrderComparator
   */
  public void onStartup(Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
      throws ServletException {

    List<WebApplicationInitializer> initializers = new LinkedList<WebApplicationInitializer>();

    if (webAppInitializerClasses != null) {
      for (Class<?> waiClass : webAppInitializerClasses) {
        // Be defensive: Some servlet containers provide us with invalid classes,
        // no matter what @HandlesTypes says...
        if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
            WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
          try {
            initializers.add((WebApplicationInitializer) waiClass.newInstance());
          }
          catch (Throwable ex) {
            throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
          }
        }
      }
    }

    if (initializers.isEmpty()) {
      servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
      return;
    }

    Collections.sort(initializers, new AnnotationAwareOrderComparator());
    servletContext.log("Spring WebApplicationInitializers detected on classpath: " + initializers);

    for (WebApplicationInitializer initializer : initializers) {
      initializer.onStartup(servletContext);
    }
  }

}
TOP

Related Classes of org.springframework.web.SpringServletContainerInitializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.