ApplicationContext-based HttpHandler setup
This commit adds support for detecting the target WebHandler along with WebFilters, WebExceptionHandlers, and other spring-web reactive strategies in an ApplicationContext. WebReactiveConfigurationSupport has @Bean factory methods for DispatcherHandler and ResponseStatusExceptionHandler. WebHttpHandlerBuilder has a static factory method that initializes the builder from an ApplicationContext. This method is also used in the DispatcherHandler#toHttpHandler(ApplicationContext) shortcut method. Issue: SPR-14837
This commit is contained in:
parent
45fc449550
commit
33dbbce182
|
|
@ -36,6 +36,7 @@ import org.springframework.web.server.ResponseStatusException;
|
|||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
/**
|
||||
* Central dispatcher for HTTP request handlers/controllers. Dispatches to registered
|
||||
|
|
@ -170,7 +171,14 @@ public class DispatcherHandler implements WebHandler, ApplicationContextAware {
|
|||
* Expose a dispatcher-based {@link HttpHandler} for the given application context,
|
||||
* typically for direct registration with an engine adapter such as
|
||||
* {@link org.springframework.http.server.reactive.ServletHttpHandlerAdapter}.
|
||||
* @param applicationContext the application context to find the handler beans in
|
||||
*
|
||||
* <p>Delegates to {@link WebHttpHandlerBuilder#applicationContext} that
|
||||
* detects the target {@link DispatcherHandler} along with
|
||||
* {@link org.springframework.web.server.WebFilter}s, and
|
||||
* {@link org.springframework.web.server.WebExceptionHandler}s in the given
|
||||
* ApplicationContext.
|
||||
*
|
||||
* @param context the application context to find the handler beans in
|
||||
* @see #DispatcherHandler(ApplicationContext)
|
||||
* @see HttpWebHandlerAdapter
|
||||
* @see org.springframework.http.server.reactive.ServletHttpHandlerAdapter
|
||||
|
|
@ -178,8 +186,8 @@ public class DispatcherHandler implements WebHandler, ApplicationContextAware {
|
|||
* @see org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter
|
||||
* @see org.springframework.http.server.reactive.UndertowHttpHandlerAdapter
|
||||
*/
|
||||
public static HttpHandler toHttpHandler(ApplicationContext applicationContext) {
|
||||
return new HttpWebHandlerAdapter(new DispatcherHandler(applicationContext));
|
||||
public static HttpHandler toHttpHandler(ApplicationContext context) {
|
||||
return WebHttpHandlerBuilder.applicationContext(context).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ import org.springframework.validation.Validator;
|
|||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.reactive.accept.CompositeContentTypeResolver;
|
||||
import org.springframework.web.reactive.accept.RequestedContentTypeResolverBuilder;
|
||||
|
|
@ -74,6 +75,8 @@ import org.springframework.web.reactive.result.method.annotation.ResponseEntityR
|
|||
import org.springframework.web.reactive.result.view.ViewResolutionResultHandler;
|
||||
import org.springframework.web.reactive.result.view.ViewResolver;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebExceptionHandler;
|
||||
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
|
||||
|
||||
/**
|
||||
* The main class for Spring Web Reactive configuration.
|
||||
|
|
@ -116,6 +119,16 @@ public class WebReactiveConfigurationSupport implements ApplicationContextAware
|
|||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public DispatcherHandler webHandler() {
|
||||
return new DispatcherHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebExceptionHandler responseStatusExceptionHandler() {
|
||||
return new ResponseStatusExceptionHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
|
||||
RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ import org.springframework.http.ResponseEntity;
|
|||
import org.springframework.http.server.reactive.AbstractHttpHandlerIntegrationTests;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
|
||||
|
||||
import static org.springframework.http.RequestEntity.get;
|
||||
import static org.springframework.http.RequestEntity.options;
|
||||
|
|
@ -53,10 +51,7 @@ public abstract class AbstractRequestMappingIntegrationTests extends AbstractHtt
|
|||
protected HttpHandler createHttpHandler() {
|
||||
this.restTemplate = initRestTemplate();
|
||||
this.applicationContext = initApplicationContext();
|
||||
return WebHttpHandlerBuilder
|
||||
.webHandler(new DispatcherHandler(this.applicationContext))
|
||||
.exceptionHandlers(new ResponseStatusExceptionHandler())
|
||||
.build();
|
||||
return WebHttpHandlerBuilder.applicationContext(this.applicationContext).build();
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
|
|
|||
|
|
@ -17,8 +17,13 @@ package org.springframework.web.server.adapter;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
|
@ -28,6 +33,7 @@ import org.springframework.web.server.WebFilter;
|
|||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.handler.ExceptionHandlingWebHandler;
|
||||
import org.springframework.web.server.handler.FilteringWebHandler;
|
||||
import org.springframework.web.server.session.DefaultWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
/**
|
||||
|
|
@ -52,6 +58,13 @@ import org.springframework.web.server.session.WebSessionManager;
|
|||
*/
|
||||
public class WebHttpHandlerBuilder {
|
||||
|
||||
/** Well-known name for the target WebHandler in the bean factory. */
|
||||
public static final String WEB_HANDLER_BEAN_NAME = "webHandler";
|
||||
|
||||
/** Well-known name for the WebSessionManager in the bean factory. */
|
||||
public static final String WEB_SESSION_MANAGER_BEAN_NAME = "webSessionManager";
|
||||
|
||||
|
||||
private final WebHandler targetHandler;
|
||||
|
||||
private final List<WebFilter> filters = new ArrayList<>();
|
||||
|
|
@ -74,11 +87,66 @@ public class WebHttpHandlerBuilder {
|
|||
/**
|
||||
* Factory method to create a new builder instance.
|
||||
* @param webHandler the target handler for the request
|
||||
* @return the prepared builder
|
||||
*/
|
||||
public static WebHttpHandlerBuilder webHandler(WebHandler webHandler) {
|
||||
return new WebHttpHandlerBuilder(webHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create a new builder instance by detecting beans in an
|
||||
* {@link ApplicationContext}. The following are detected:
|
||||
* <ul>
|
||||
* <li>{@link WebHandler} [1] -- looked up by the name
|
||||
* {@link #WEB_HANDLER_BEAN_NAME}.
|
||||
* <li>{@link WebFilter} [0..N] -- detected by type and ordered,
|
||||
* see {@link AnnotationAwareOrderComparator}.
|
||||
* <li>{@link WebExceptionHandler} [0..N] -- detected by type and
|
||||
* ordered.
|
||||
* <li>{@link WebSessionManager} [0..1] -- looked up by the name
|
||||
* {@link #WEB_SESSION_MANAGER_BEAN_NAME}.
|
||||
* </ul>
|
||||
* @param context the application context to use for the lookup
|
||||
* @return the prepared builder
|
||||
*/
|
||||
public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) {
|
||||
|
||||
// Target WebHandler
|
||||
|
||||
WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder(
|
||||
context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class));
|
||||
|
||||
// WebFilter...
|
||||
|
||||
Collection<WebFilter> filters = BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
context, WebFilter.class, true, false).values();
|
||||
|
||||
WebFilter[] sortedFilters = filters.toArray(new WebFilter[filters.size()]);
|
||||
AnnotationAwareOrderComparator.sort(sortedFilters);
|
||||
builder.filters(sortedFilters);
|
||||
|
||||
// WebExceptionHandler...
|
||||
|
||||
Collection<WebExceptionHandler> handlers = BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
context, WebExceptionHandler.class, true, false).values();
|
||||
|
||||
WebExceptionHandler[] sortedHandlers = handlers.toArray(new WebExceptionHandler[handlers.size()]);
|
||||
AnnotationAwareOrderComparator.sort(sortedHandlers);
|
||||
builder.exceptionHandlers(sortedHandlers);
|
||||
|
||||
// WebSessionManager
|
||||
|
||||
try {
|
||||
builder.sessionManager(
|
||||
context.getBean(WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class));
|
||||
}
|
||||
catch (NoSuchBeanDefinitionException ex) {
|
||||
// Fall back on default
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given filters to use for processing requests.
|
||||
|
|
@ -104,8 +172,8 @@ public class WebHttpHandlerBuilder {
|
|||
|
||||
/**
|
||||
* Configure the {@link WebSessionManager} to set on the
|
||||
* {@link ServerWebExchange WebServerExchange}
|
||||
* created for each HTTP request.
|
||||
* {@link ServerWebExchange WebServerExchange}.
|
||||
* <p>By default {@link DefaultWebSessionManager} is used.
|
||||
* @param sessionManager the session manager
|
||||
* @see HttpWebHandlerAdapter#setSessionManager(WebSessionManager)
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue