Update information on WebApplicationContext hierarchy

Issue: SPR-16041
This commit is contained in:
Rossen Stoyanchev 2017-10-17 21:49:57 -04:00
parent cd634633d8
commit 32d78e60b6
7 changed files with 76 additions and 73 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -20,13 +20,11 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.reactive.DispatcherHandler;
/** /**
* Base class for {@link org.springframework.web.WebApplicationInitializer} * {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializer}
* implementations that register a {@link DispatcherHandler} configured with annotated * to register a {@code DispatcherHandler}, wrapping it in a
* {@link org.springframework.context.annotation.Configuration @Configuration} classes in the * {@link ServletHttpHandlerAdapter}, and use Java-based Spring configuration.
* servlet context, wrapping it in a {@link ServletHttpHandlerAdapter}.
* *
* <p>Concrete implementations are required to implement {@link #getConfigClasses()}. * <p>Concrete implementations are required to implement {@link #getConfigClasses()}.
* Further template and customization methods are provided by * Further template and customization methods are provided by
@ -38,6 +36,7 @@ import org.springframework.web.reactive.DispatcherHandler;
public abstract class AbstractAnnotationConfigDispatcherHandlerInitializer public abstract class AbstractAnnotationConfigDispatcherHandlerInitializer
extends AbstractDispatcherHandlerInitializer { extends AbstractDispatcherHandlerInitializer {
/** /**
* {@inheritDoc} * {@inheritDoc}
* <p>This implementation creates an {@link AnnotationConfigApplicationContext}, * <p>This implementation creates an {@link AnnotationConfigApplicationContext},
@ -45,19 +44,18 @@ public abstract class AbstractAnnotationConfigDispatcherHandlerInitializer
*/ */
@Override @Override
protected ApplicationContext createApplicationContext() { protected ApplicationContext createApplicationContext() {
AnnotationConfigApplicationContext servletAppContext = new AnnotationConfigApplicationContext(); AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
Class<?>[] configClasses = getConfigClasses(); Class<?>[] configClasses = getConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) { if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses); context.register(configClasses);
} }
return servletAppContext; return context;
} }
/** /**
* Specify {@link org.springframework.context.annotation.Configuration @Configuration} * Specify {@code @Configuration} and/or {@code @Component} classes for
* and/or {@link org.springframework.stereotype.Component @Component} classes to be * the {@linkplain #createApplicationContext() application context}.
* provided to the {@linkplain #createApplicationContext() application context}. * @return the configuration for the application context
* @return the configuration classes for the dispatcher servlet application context
*/ */
protected abstract Class<?>[] getConfigClasses(); protected abstract Class<?>[] getConfigClasses();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,16 +34,15 @@ import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
/** /**
* Base class for {@link org.springframework.web.WebApplicationInitializer} * Base class for {@link org.springframework.web.WebApplicationInitializer}
* implementations that register a {@link DispatcherHandler} in the servlet context, wrapping it in * implementations that register a {@link DispatcherHandler} in the servlet
* a {@link ServletHttpHandlerAdapter}. * context, wrapping it in a {@link ServletHttpHandlerAdapter}.
* *
* <p>Concrete implementations are required to implement * <p>Most applications should consider extending the Spring Java config, sub-class
* {@link #createApplicationContext()}, which gets invoked from * {@link AbstractAnnotationConfigDispatcherHandlerInitializer}.
* {@link #registerDispatcherHandler(ServletContext)}. Further customization can be achieved by
* overriding {@link #customizeRegistration(ServletRegistration.Dynamic)}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 5.0 * @since 5.0
* @see AbstractServletHttpHandlerAdapterInitializer
*/ */
public abstract class AbstractDispatcherHandlerInitializer implements WebApplicationInitializer { public abstract class AbstractDispatcherHandlerInitializer implements WebApplicationInitializer {

View File

@ -27,16 +27,15 @@ import org.springframework.web.WebApplicationInitializer;
/** /**
* Base class for {@link org.springframework.web.WebApplicationInitializer} * Base class for {@link org.springframework.web.WebApplicationInitializer}
* implementations that register a {@link ServletHttpHandlerAdapter} in the servlet context. * implementations that register a {@link ServletHttpHandlerAdapter} in the
* servlet context.
* *
* <p>Concrete implementations are required to implement * <p>See {@link AbstractDispatcherHandlerInitializer} if registering a
* {@link #createHttpHandler()}, as well as {@link #getServletMappings()}, * {@link org.springframework.web.reactive.DispatcherHandler DispatcherHandler}.
* both of which get invoked from {@link #registerHandlerAdapter(ServletContext)}.
* Further customization can be achieved by overriding
* {@link #customizeRegistration(ServletRegistration.Dynamic)}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 5.0 * @since 5.0
* @see AbstractDispatcherHandlerInitializer
*/ */
public abstract class AbstractServletHttpHandlerAdapterInitializer implements WebApplicationInitializer { public abstract class AbstractServletHttpHandlerAdapterInitializer implements WebApplicationInitializer {
@ -67,12 +66,12 @@ public abstract class AbstractServletHttpHandlerAdapterInitializer implements We
Assert.hasLength(servletName, "getServletName() must not return empty or null"); Assert.hasLength(servletName, "getServletName() must not return empty or null");
HttpHandler httpHandler = createHttpHandler(); HttpHandler httpHandler = createHttpHandler();
Assert.notNull(httpHandler, Assert.notNull(httpHandler, "createHttpHandler() did not return a HttpHandler" +
"createHttpHandler() did not return a HttpHandler for servlet [" + servletName + "]"); "for servlet [" + servletName + "]");
ServletHttpHandlerAdapter servlet = createServlet(httpHandler); ServletHttpHandlerAdapter servlet = createServlet(httpHandler);
Assert.notNull(servlet, Assert.notNull(servlet, "createHttpHandler() did not return a ServletHttpHandlerAdapter " +
"createHttpHandler() did not return a ServletHttpHandlerAdapter for servlet [" + servletName + "]"); "for servlet [" + servletName + "]");
ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, servlet); ServletRegistration.Dynamic registration = servletContext.addServlet(servletName, servlet);
Assert.notNull(registration, Assert.notNull(registration,
@ -102,8 +101,8 @@ public abstract class AbstractServletHttpHandlerAdapterInitializer implements We
/** /**
* Create a {@link ServletHttpHandlerAdapter} with the specified . * Create a {@link ServletHttpHandlerAdapter} with the specified .
* <p>Default implementation returns a {@code ServletHttpHandlerAdapter} with the provided * <p>Default implementation returns a {@code ServletHttpHandlerAdapter}
* {@code httpHandler}. * with the provided {@code httpHandler}.
*/ */
protected ServletHttpHandlerAdapter createServlet(HttpHandler httpHandler) { protected ServletHttpHandlerAdapter createServlet(HttpHandler httpHandler) {
return new ServletHttpHandlerAdapter(httpHandler); return new ServletHttpHandlerAdapter(httpHandler);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,19 +22,20 @@ import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
/** /**
* Base class for {@link org.springframework.web.WebApplicationInitializer} * {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializer}
* implementations that register a * to register a {@code DispatcherServlet} and use Java-based Spring configuration.
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
* configured with annotated classes, e.g. Spring's
* {@link org.springframework.context.annotation.Configuration @Configuration} classes.
* *
* <p>Concrete implementations are required to implement {@link #getRootConfigClasses()} * <p>Implementations are required to implement:
* and {@link #getServletConfigClasses()} as well as {@link #getServletMappings()}. * <ul>
* Further template and customization methods are provided by * <li>{@link #getRootConfigClasses()} -- for "root" application context (non-web
* {@link AbstractDispatcherServletInitializer}. * infrastructure) configuration.
* <li>{@link #getServletConfigClasses()} -- for {@code DispatcherServlet}
* application context (Spring MVC infrastructure) configuration.
* </ul>
* *
* <p>This is the preferred approach for applications that use Java-based * <p>If an application context hierarchy is not required, applications may
* Spring configuration. * return all configuration via {@link #getRootConfigClasses()} and return
* {@code null} from {@link #getServletConfigClasses()}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Chris Beams * @author Chris Beams
@ -54,9 +55,9 @@ public abstract class AbstractAnnotationConfigDispatcherServletInitializer
protected WebApplicationContext createRootApplicationContext() { protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses(); Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) { if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext(); AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses); context.register(configClasses);
return rootAppContext; return context;
} }
else { else {
return null; return null;
@ -70,30 +71,27 @@ public abstract class AbstractAnnotationConfigDispatcherServletInitializer
*/ */
@Override @Override
protected WebApplicationContext createServletApplicationContext() { protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext(); AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses(); Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) { if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses); context.register(configClasses);
} }
return servletAppContext; return context;
} }
/** /**
* Specify {@link org.springframework.context.annotation.Configuration @Configuration} * Specify {@code @Configuration} and/or {@code @Component} classes for the
* and/or {@link org.springframework.stereotype.Component @Component} classes to be * {@linkplain #createRootApplicationContext() root application context}.
* provided to the {@linkplain #createRootApplicationContext() root application context}. * @return the configuration for the root application context, or {@code null}
* @return the configuration classes for the root application context, or {@code null}
* if creation and registration of a root context is not desired * if creation and registration of a root context is not desired
*/ */
@Nullable @Nullable
protected abstract Class<?>[] getRootConfigClasses(); protected abstract Class<?>[] getRootConfigClasses();
/** /**
* Specify {@link org.springframework.context.annotation.Configuration @Configuration} * Specify {@code @Configuration} and/or {@code @Component} classes for the
* and/or {@link org.springframework.stereotype.Component @Component} classes to be * {@linkplain #createServletApplicationContext() Servlet application context}.
* provided to the {@linkplain #createServletApplicationContext() dispatcher servlet * @return the configuration for the Servlet application context, or
* application context}.
* @return the configuration classes for the dispatcher servlet application context or
* {@code null} if all configuration is specified through root config classes. * {@code null} if all configuration is specified through root config classes.
*/ */
@Nullable @Nullable

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2015 the original author or authors. * Copyright 2002-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -40,17 +40,8 @@ import org.springframework.web.servlet.FrameworkServlet;
* Base class for {@link org.springframework.web.WebApplicationInitializer} * Base class for {@link org.springframework.web.WebApplicationInitializer}
* implementations that register a {@link DispatcherServlet} in the servlet context. * implementations that register a {@link DispatcherServlet} in the servlet context.
* *
* <p>Concrete implementations are required to implement * <p>Most applications should consider extending the Spring Java config, sub-class
* {@link #createServletApplicationContext()}, as well as {@link #getServletMappings()}, * {@link AbstractAnnotationConfigDispatcherServletInitializer}.
* both of which get invoked from {@link #registerDispatcherServlet(ServletContext)}.
* Further customization can be achieved by overriding
* {@link #customizeRegistration(ServletRegistration.Dynamic)}.
*
* <p>Because this class extends from {@link AbstractContextLoaderInitializer}, concrete
* implementations are also required to implement {@link #createRootApplicationContext()}
* to set up a parent "<strong>root</strong>" application context. If a root context is
* not desired, implementations can simply return {@code null} in the
* {@code createRootApplicationContext()} implementation.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Chris Beams * @author Chris Beams

View File

@ -346,8 +346,13 @@ server.addConnector(connector);
server.start(); server.start();
---- ----
You can also deploy as a WAR to any Servlet 3.1 container by wrapping the handler with [NOTE]
`ServletHttpHandlerAdapter` as a `Servlet`. ====
To deploy as a WAR to a Servlet 3.1+ container, wrap `HttpHandler` with
`ServletHttpHandlerAdapter` and register that as a `Servlet`. Use
{api-spring-framework}/web/reactive/support/AbstractServletHttpHandlerAdapterInitializer.html[AbstractServletHttpHandlerAdapterInitializer]
to automate the required Servlet container configuration.
====

View File

@ -161,6 +161,12 @@ Below is example configuration with a `WebApplicationContext` hierarchy:
} }
---- ----
[TIP]
====
If an application context hierarchy is not required, applications may return all
configuration via `getRootConfigClasses()` and `null` from `getServletConfigClasses()`.
====
And the `web.xml` equivalent: And the `web.xml` equivalent:
[source,xml,indent=0] [source,xml,indent=0]
@ -195,6 +201,13 @@ And the `web.xml` equivalent:
</web-app> </web-app>
---- ----
[TIP]
====
If an application context hierarchy is not required, applications may configure a
"root" context only and leave the `contextConfigLocation` Servlet parameter empty.
====
[[mvc-servlet-special-bean-types]] [[mvc-servlet-special-bean-types]]