All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.web.server.adapter.WebHttpHandlerBuilder Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2017 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.server.adapter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
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.i18n.LocaleContextResolver;
import org.springframework.web.server.session.DefaultWebSessionManager;
import org.springframework.web.server.session.WebSessionManager;

/**
 * This builder has two purposes.
 *
 * 

One is to assemble a processing chain that consists of a target * {@link WebHandler}, then decorated with a set of {@link WebFilter}'s, then * further decorated with a set of {@link WebExceptionHandler}'s. * *

The second purpose is to adapt the resulting processing chain to an * {@link HttpHandler} -- the lowest level reactive HTTP handling abstraction, * which can then be used with any of the supported runtimes. The adaptation * is done with the help of {@link HttpWebHandlerAdapter}. * *

The processing chain can be assembled manually via builder methods, or * detected from Spring configuration via * {@link #applicationContext(ApplicationContext)}, or a mix of both. * * @author Rossen Stoyanchev * @author Sebastien Deleuze * @since 5.0 * @see HttpWebHandlerAdapter */ 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"; /** Well-known name for the ServerCodecConfigurer in the bean factory. */ public static final String SERVER_CODEC_CONFIGURER_BEAN_NAME = "serverCodecConfigurer"; /** Well-known name for the LocaleContextResolver in the bean factory. */ public static final String LOCALE_CONTEXT_RESOLVER_BEAN_NAME = "localeContextResolver"; private final WebHandler webHandler; private final List filters = new ArrayList<>(); private final List exceptionHandlers = new ArrayList<>(); @Nullable private WebSessionManager sessionManager; @Nullable private ServerCodecConfigurer codecConfigurer; @Nullable private LocaleContextResolver localeContextResolver; @Nullable private ApplicationContext applicationContext; /** * Private constructor. */ private WebHttpHandlerBuilder(WebHandler webHandler) { Assert.notNull(webHandler, "WebHandler must not be null"); this.webHandler = webHandler; } /** * Private constructor to use when initialized from an ApplicationContext. */ private WebHttpHandlerBuilder(WebHandler webHandler, ApplicationContext applicationContext) { Assert.notNull(webHandler, "WebHandler must not be null"); this.webHandler = webHandler; this.applicationContext = applicationContext; } /** * Copy constructor. */ private WebHttpHandlerBuilder(WebHttpHandlerBuilder other) { this.webHandler = other.webHandler; this.filters.addAll(other.filters); this.exceptionHandlers.addAll(other.exceptionHandlers); this.sessionManager = other.sessionManager; this.codecConfigurer = other.codecConfigurer; this.localeContextResolver = other.localeContextResolver; } /** * Static 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); } /** * Static factory method to create a new builder instance by detecting beans * in an {@link ApplicationContext}. The following are detected: *

    *
  • {@link WebHandler} [1] -- looked up by the name * {@link #WEB_HANDLER_BEAN_NAME}. *
  • {@link WebFilter} [0..N] -- detected by type and ordered, * see {@link AnnotationAwareOrderComparator}. *
  • {@link WebExceptionHandler} [0..N] -- detected by type and * ordered. *
  • {@link WebSessionManager} [0..1] -- looked up by the name * {@link #WEB_SESSION_MANAGER_BEAN_NAME}. *
  • {@link ServerCodecConfigurer} [0..1] -- looked up by the name * {@link #SERVER_CODEC_CONFIGURER_BEAN_NAME}. *
  • {@link LocaleContextResolver} [0..1] -- looked up by the name * {@link #LOCALE_CONTEXT_RESOLVER_BEAN_NAME}. *
* @param context the application context to use for the lookup * @return the prepared builder */ public static WebHttpHandlerBuilder applicationContext(ApplicationContext context) { WebHttpHandlerBuilder builder = new WebHttpHandlerBuilder( context.getBean(WEB_HANDLER_BEAN_NAME, WebHandler.class), context); // Autowire lists for @Bean + @Order SortedBeanContainer container = new SortedBeanContainer(); context.getAutowireCapableBeanFactory().autowireBean(container); builder.filters(filters -> filters.addAll(container.getFilters())); builder.exceptionHandlers(handlers -> handlers.addAll(container.getExceptionHandlers())); try { builder.sessionManager( context.getBean(WEB_SESSION_MANAGER_BEAN_NAME, WebSessionManager.class)); } catch (NoSuchBeanDefinitionException ex) { // Fall back on default } try { builder.codecConfigurer( context.getBean(SERVER_CODEC_CONFIGURER_BEAN_NAME, ServerCodecConfigurer.class)); } catch (NoSuchBeanDefinitionException ex) { // Fall back on default } try { builder.localeContextResolver( context.getBean(LOCALE_CONTEXT_RESOLVER_BEAN_NAME, LocaleContextResolver.class)); } catch (NoSuchBeanDefinitionException ex) { // Fall back on default } return builder; } /** * Add the given filter(s). * @param filters the filter(s) to add that's */ public WebHttpHandlerBuilder filter(WebFilter... filters) { if (!ObjectUtils.isEmpty(filters)) { this.filters.addAll(Arrays.asList(filters)); } return this; } /** * Manipulate the "live" list of currently configured filters. * @param consumer the consumer to use */ public WebHttpHandlerBuilder filters(Consumer> consumer) { consumer.accept(this.filters); return this; } /** * Add the given exception handler(s). * @param handlers the exception handler(s) */ public WebHttpHandlerBuilder exceptionHandler(WebExceptionHandler... handlers) { if (!ObjectUtils.isEmpty(handlers)) { this.exceptionHandlers.addAll(Arrays.asList(handlers)); } return this; } /** * Manipulate the "live" list of currently configured exception handlers. * @param consumer the consumer to use */ public WebHttpHandlerBuilder exceptionHandlers(Consumer> consumer) { consumer.accept(this.exceptionHandlers); return this; } /** * Configure the {@link WebSessionManager} to set on the * {@link ServerWebExchange WebServerExchange}. *

By default {@link DefaultWebSessionManager} is used. * @param manager the session manager * @see HttpWebHandlerAdapter#setSessionManager(WebSessionManager) */ public WebHttpHandlerBuilder sessionManager(WebSessionManager manager) { this.sessionManager = manager; return this; } /** * Configure the {@link ServerCodecConfigurer} to set on the * {@link ServerWebExchange WebServerExchange}. * @param codecConfigurer the codec configurer */ public WebHttpHandlerBuilder codecConfigurer(ServerCodecConfigurer codecConfigurer) { this.codecConfigurer = codecConfigurer; return this; } /** * Configure the {@link LocaleContextResolver} to set on the * {@link ServerWebExchange WebServerExchange}. * @param localeContextResolver the locale context resolver */ public WebHttpHandlerBuilder localeContextResolver(LocaleContextResolver localeContextResolver) { this.localeContextResolver = localeContextResolver; return this; } /** * Build the {@link HttpHandler}. */ public HttpHandler build() { WebHandler decorated; decorated = new FilteringWebHandler(this.webHandler, this.filters); decorated = new ExceptionHandlingWebHandler(decorated, this.exceptionHandlers); HttpWebHandlerAdapter adapted = new HttpWebHandlerAdapter(decorated); if (this.sessionManager != null) { adapted.setSessionManager(this.sessionManager); } if (this.codecConfigurer != null) { adapted.setCodecConfigurer(this.codecConfigurer); } if (this.localeContextResolver != null) { adapted.setLocaleContextResolver(this.localeContextResolver); } if (this.applicationContext != null) { adapted.setApplicationContext(this.applicationContext); } return adapted; } /** * Clone this {@link WebHttpHandlerBuilder}. * @return the cloned builder instance */ @Override public WebHttpHandlerBuilder clone() { return new WebHttpHandlerBuilder(this); } private static class SortedBeanContainer { private List filters = Collections.emptyList(); private List exceptionHandlers = Collections.emptyList(); @Autowired(required = false) public void setFilters(List filters) { this.filters = filters; } public List getFilters() { return this.filters; } @Autowired(required = false) public void setExceptionHandlers(List exceptionHandlers) { this.exceptionHandlers = exceptionHandlers; } public List getExceptionHandlers() { return this.exceptionHandlers; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy