Unify WebServerFactoryCustomizers

Replace `ReactiveWebServerCustomizer` and `WebServerFactoryCustomizer`
with a unified `WebServerFactoryCustomizer`.

Fixes gh-8558
This commit is contained in:
Phillip Webb
2017-03-14 15:48:02 -07:00
parent 13db69bf41
commit 099e188f9f
30 changed files with 487 additions and 403 deletions

View File

@@ -48,9 +48,8 @@ import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactor
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -171,8 +170,8 @@ public class EndpointWebMvcChildContextConfiguration {
}
static class ServerFactoryCustomization
implements ServletWebServerFactoryCustomizer, Ordered {
static class ServerFactoryCustomization implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
@Autowired
private ListableBeanFactory beanFactory;
@@ -215,7 +214,8 @@ public class EndpointWebMvcChildContextConfiguration {
}
webServerFactory.setServerHeader(this.server.getServerHeader());
webServerFactory.setAddress(this.managementServerProperties.getAddress());
webServerFactory.addErrorPages(new ErrorPage(this.server.getError().getPath()));
webServerFactory
.addErrorPages(new ErrorPage(this.server.getError().getPath()));
}
}
@@ -343,14 +343,7 @@ public class EndpointWebMvcChildContextConfiguration {
}
static abstract class AccessLogCustomizer<T extends ServletWebServerFactory>
implements ServletWebServerFactoryCustomizer, Ordered {
private final Class<T> factoryClass;
AccessLogCustomizer(Class<T> factoryClass) {
this.factoryClass = factoryClass;
}
static abstract class AccessLogCustomizer implements Ordered {
protected String customizePrefix(String prefix) {
return "management_" + prefix;
@@ -361,23 +354,10 @@ public class EndpointWebMvcChildContextConfiguration {
return 1;
}
@Override
public void customize(ConfigurableServletWebServerFactory serverFactory) {
if (this.factoryClass.isInstance(serverFactory)) {
customize(this.factoryClass.cast(serverFactory));
}
}
abstract void customize(T webServerFactory);
}
static class TomcatAccessLogCustomizer
extends AccessLogCustomizer<TomcatServletWebServerFactory> {
TomcatAccessLogCustomizer() {
super(TomcatServletWebServerFactory.class);
}
static class TomcatAccessLogCustomizer extends AccessLogCustomizer
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory serverFactory) {
@@ -400,16 +380,13 @@ public class EndpointWebMvcChildContextConfiguration {
}
static class UndertowAccessLogCustomizer
extends AccessLogCustomizer<UndertowServletWebServerFactory> {
UndertowAccessLogCustomizer() {
super(UndertowServletWebServerFactory.class);
}
static class UndertowAccessLogCustomizer extends AccessLogCustomizer
implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory serverFactory) {
serverFactory.setAccessLogPrefix(customizePrefix(serverFactory.getAccessLogPrefix()));
serverFactory.setAccessLogPrefix(
customizePrefix(serverFactory.getAccessLogPrefix()));
}
}

View File

@@ -32,10 +32,10 @@ import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfi
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.servlet.MockMvc;
@@ -162,8 +162,8 @@ public class JolokiaAutoConfigurationTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -50,12 +50,10 @@ import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowBuilderCustomizer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.InitParameterConfiguringServletContextInitializer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.Ordered;
import org.springframework.core.env.Environment;
@@ -63,15 +61,15 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Customizer used by an {@link ServletWebServerFactory} when an
* {@link ServletWebServerFactoryCustomizerBeanPostProcessor} is active.
* Default {@link WebServerFactoryCustomizer} for {@link ServerProperties}.
*
* @author Brian Clozel
* @author Stephane Nicoll
* @since 2.0.0
*/
public class DefaultServletWebServerFactoryCustomizer
implements ServletWebServerFactoryCustomizer, EnvironmentAware, Ordered {
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>,
EnvironmentAware, Ordered {
private final ServerProperties serverProperties;

View File

@@ -48,7 +48,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;

View File

@@ -23,9 +23,9 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.HttpEncodingProperties.Type;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
@@ -67,8 +67,8 @@ public class HttpEncodingAutoConfiguration {
return new LocaleCharsetMappingsCustomizer(this.properties);
}
private static class LocaleCharsetMappingsCustomizer
implements ServletWebServerFactoryCustomizer, Ordered {
private static class LocaleCharsetMappingsCustomizer implements
WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
private final HttpEncodingProperties properties;

View File

@@ -44,8 +44,8 @@ import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -124,8 +124,8 @@ public class ServletWebServerFactoryAutoConfiguration {
}
/**
* Registers a {@link ServletWebServerFactoryCustomizerBeanPostProcessor}. Registered
* via {@link ImportBeanDefinitionRegistrar} for early registration.
* Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
* {@link ImportBeanDefinitionRegistrar} for early registration.
*/
public static class BeanPostProcessorsRegistrar
implements ImportBeanDefinitionRegistrar, BeanFactoryAware {
@@ -146,8 +146,8 @@ public class ServletWebServerFactoryAutoConfiguration {
return;
}
registerSyntheticBeanIfMissing(registry,
"ServletWebServerCustomizerBeanPostProcessor",
ServletWebServerFactoryCustomizerBeanPostProcessor.class);
"webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry,
"errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class);

View File

@@ -18,20 +18,17 @@ package org.springframework.boot.autoconfigure.webflux;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerCustomizer;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;
/**
* Customizer used by an {@link ReactiveWebServerFactory} when an
* {@link ServletWebServerFactoryCustomizerBeanPostProcessor} is active.
* Default {@link WebServerFactoryCustomizer} for reactive servers.
*
* @author Brian Clozel
* @since 2.0.0
*/
public class DefaultReactiveWebServerCustomizer
implements ReactiveWebServerCustomizer, Ordered {
public class DefaultReactiveWebServerCustomizer implements
WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory>, Ordered {
private final ServerProperties serverProperties;

View File

@@ -28,7 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.server.ReactiveWebServerCustomizerBeanPostProcessor;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -62,7 +62,7 @@ public class ReactiveWebServerAutoConfiguration {
}
/**
* Registers a {@link ReactiveWebServerCustomizerBeanPostProcessor}. Registered via
* Registers a {@link WebServerFactoryCustomizerBeanPostProcessor}. Registered via
* {@link ImportBeanDefinitionRegistrar} for early registration.
*/
public static class BeanPostProcessorsRegistrar
@@ -84,12 +84,12 @@ public class ReactiveWebServerAutoConfiguration {
return;
}
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(
ReactiveWebServerCustomizerBeanPostProcessor.class, true, false))) {
WebServerFactoryCustomizerBeanPostProcessor.class, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(
ReactiveWebServerCustomizerBeanPostProcessor.class);
WebServerFactoryCustomizerBeanPostProcessor.class);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(
"reactiveWebServerCustomizerBeanPostProcessor", beanDefinition);
"webServerFactoryCustomizerBeanPostProcessor", beanDefinition);
}
}

View File

@@ -23,9 +23,11 @@ import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;
/**
* {@link WebSocketContainerCustomizer} for {@link JettyServletWebServerFactory}.
* WebSocket customizer for {@link JettyServletWebServerFactory}.
*
* @author Dave Syer
* @author Phillip Webb
@@ -33,10 +35,10 @@ import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
* @since 1.2.0
*/
public class JettyWebSocketContainerCustomizer
extends WebSocketContainerCustomizer<JettyServletWebServerFactory> {
implements WebServerFactoryCustomizer<JettyServletWebServerFactory>, Ordered {
@Override
protected void doCustomize(JettyServletWebServerFactory factory) {
public void customize(JettyServletWebServerFactory factory) {
factory.addConfigurations(new AbstractConfiguration() {
@Override
@@ -49,4 +51,9 @@ public class JettyWebSocketContainerCustomizer
});
}
@Override
public int getOrder() {
return 0;
}
}

View File

@@ -23,11 +23,13 @@ import org.apache.catalina.Context;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* {@link WebSocketContainerCustomizer} for {@link TomcatServletWebServerFactory}.
* WebSocket customizer for {@link TomcatServletWebServerFactory}.
*
* @author Dave Syer
* @author Phillip Webb
@@ -35,7 +37,7 @@ import org.springframework.util.ReflectionUtils;
* @since 1.2.0
*/
public class TomcatWebSocketContainerCustomizer
extends WebSocketContainerCustomizer<TomcatServletWebServerFactory> {
implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>, Ordered {
private static final String TOMCAT_7_LISTENER_TYPE = "org.apache.catalina.deploy.ApplicationListener";
@@ -44,7 +46,7 @@ public class TomcatWebSocketContainerCustomizer
private static final String WS_LISTENER = "org.apache.tomcat.websocket.server.WsContextListener";
@Override
public void doCustomize(TomcatServletWebServerFactory factory) {
public void customize(TomcatServletWebServerFactory factory) {
factory.addContextCustomizers(new TomcatContextCustomizer() {
@Override
@@ -89,4 +91,9 @@ public class TomcatWebSocketContainerCustomizer
}
}
@Override
public int getOrder() {
return 0;
}
}

View File

@@ -21,22 +21,29 @@ import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowDeploymentInfoCustomizer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.core.Ordered;
/**
* {@link WebSocketContainerCustomizer} for {@link UndertowServletWebServerFactory}.
* WebSocket customizer for {@link UndertowServletWebServerFactory}.
*
* @author Phillip Webb
* @since 1.2.0
*/
public class UndertowWebSocketContainerCustomizer
extends WebSocketContainerCustomizer<UndertowServletWebServerFactory> {
implements WebServerFactoryCustomizer<UndertowServletWebServerFactory>, Ordered {
@Override
protected void doCustomize(UndertowServletWebServerFactory factory) {
public void customize(UndertowServletWebServerFactory factory) {
WebsocketDeploymentInfoCustomizer customizer = new WebsocketDeploymentInfoCustomizer();
factory.addDeploymentInfoCustomizers(customizer);
}
@Override
public int getOrder() {
return 0;
}
private static class WebsocketDeploymentInfoCustomizer
implements UndertowDeploymentInfoCustomizer {

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2012-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.boot.autoconfigure.websocket;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
/**
* {@link ServletWebServerFactoryCustomizer} to configure websockets for a given
* {@link ServletWebServerFactory}.
*
* @param <T> the {@link ServletWebServerFactory}
* @author Dave Syer
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.2.0
*/
public abstract class WebSocketContainerCustomizer<T extends ServletWebServerFactory>
implements ServletWebServerFactoryCustomizer, Ordered {
@Override
public int getOrder() {
return 0;
}
@SuppressWarnings("unchecked")
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
if (getWebServerFactoryType().isAssignableFrom(factory.getClass())) {
doCustomize((T) factory);
}
}
protected Class<?> getWebServerFactoryType() {
return ResolvableType.forClass(WebSocketContainerCustomizer.class, getClass())
.resolveGeneric();
}
protected abstract void doCustomize(T factory);
}

View File

@@ -34,12 +34,12 @@ import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.util.ReflectionTestUtils;
@@ -165,8 +165,8 @@ public class DefaultServletWebServerFactoryCustomizerTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}
@@ -183,8 +183,8 @@ public class DefaultServletWebServerFactoryCustomizerTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}
@@ -201,8 +201,8 @@ public class DefaultServletWebServerFactoryCustomizerTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}
@@ -211,15 +211,8 @@ public class DefaultServletWebServerFactoryCustomizerTests {
protected static class CustomizeConfig {
@Bean
public ServletWebServerFactoryCustomizer webServerFactoryCustomizer() {
return new ServletWebServerFactoryCustomizer() {
@Override
public void customize(ConfigurableServletWebServerFactory serverFactory) {
serverFactory.setPort(3000);
}
};
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> webServerFactoryCustomizer() {
return (serverFactory) -> serverFactory.setPort(3000);
}
}

View File

@@ -29,12 +29,12 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory.RegisteredFilter;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
@@ -104,8 +104,8 @@ public class FilterOrderingIntegrationTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -31,11 +31,11 @@ import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter;
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
@@ -145,8 +145,7 @@ public class HttpEncodingAutoConfigurationTests {
@Test
public void noLocaleCharsetMapping() {
load(EmptyConfiguration.class);
Map<String, ServletWebServerFactoryCustomizer> beans = this.context
.getBeansOfType(ServletWebServerFactoryCustomizer.class);
Map<String, WebServerFactoryCustomizer<?>> beans = getWebServerFactoryCustomizerBeans();
assertThat(beans.size()).isEqualTo(1);
assertThat(this.context.getBean(MockServletWebServerFactory.class)
.getLocaleCharsetMappings().size()).isEqualTo(0);
@@ -156,8 +155,7 @@ public class HttpEncodingAutoConfigurationTests {
public void customLocaleCharsetMappings() {
load(EmptyConfiguration.class, "spring.http.encoding.mapping.en:UTF-8",
"spring.http.encoding.mapping.fr_FR:UTF-8");
Map<String, ServletWebServerFactoryCustomizer> beans = this.context
.getBeansOfType(ServletWebServerFactoryCustomizer.class);
Map<String, WebServerFactoryCustomizer<?>> beans = getWebServerFactoryCustomizerBeans();
assertThat(beans.size()).isEqualTo(1);
assertThat(this.context.getBean(MockServletWebServerFactory.class)
.getLocaleCharsetMappings().size()).isEqualTo(2);
@@ -169,6 +167,11 @@ public class HttpEncodingAutoConfigurationTests {
.isEqualTo(Charset.forName("UTF-8"));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Map<String, WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
return (Map) this.context.getBeansOfType(WebServerFactoryCustomizer.class);
}
private void assertCharacterEncodingFilter(CharacterEncodingFilter actual,
String encoding, boolean forceRequestEncoding,
boolean forceResponseEncoding) {
@@ -235,8 +238,8 @@ public class HttpEncodingAutoConfigurationTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -44,9 +44,9 @@ import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.mock.env.MockEnvironment;
import static org.assertj.core.api.Assertions.assertThat;
@@ -59,7 +59,7 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link ServerProperties} {@link ServletWebServerFactoryCustomizer}.
* Tests for {@link ServerProperties} {@link WebServerFactoryCustomizer}.
*
* @author Brian Clozel
*/

View File

@@ -27,12 +27,12 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -246,7 +246,7 @@ public class ServletWebServerFactoryAutoConfigurationTests {
@Component
public static class CallbackEmbeddedServerFactoryCustomizer
implements ServletWebServerFactoryCustomizer {
implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory serverFactory) {

View File

@@ -43,11 +43,11 @@ import org.springframework.boot.autoconfigure.validation.SpringValidator;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.WelcomePageHandlerMapping;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.filter.OrderedHttpPutFormContentFilter;
import org.springframework.boot.web.servlet.server.MockServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -773,8 +773,8 @@ public class WebMvcAutoConfigurationTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -23,8 +23,9 @@ import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext;
import org.springframework.boot.web.reactive.server.ReactiveWebServerCustomizer;
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -50,7 +51,7 @@ public class ReactiveWebServerAutoConfigurationTests {
this.context = new ReactiveWebServerApplicationContext(BaseConfiguration.class);
assertThat(this.context.getBeansOfType(ReactiveWebServerFactory.class))
.hasSize(1);
assertThat(this.context.getBeansOfType(ReactiveWebServerCustomizer.class))
assertThat(this.context.getBeansOfType(WebServerFactoryCustomizer.class))
.hasSize(1);
assertThat(this.context.getBeansOfType(DefaultReactiveWebServerCustomizer.class))
.hasSize(1);
@@ -115,7 +116,7 @@ public class ReactiveWebServerAutoConfigurationTests {
protected static class ReactiveWebServerCustomization {
@Bean
public ReactiveWebServerCustomizer reactiveWebServerCustomizer() {
public WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> reactiveWebServerCustomizer() {
return (server) -> server.setPort(9000);
}

View File

@@ -29,9 +29,9 @@ import org.junit.Test;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.util.ReflectionTestUtils;
@@ -92,8 +92,8 @@ public class WebSocketAutoConfigurationTests {
static class CommonConfiguration {
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor ServletWebServerCustomizerBeanPostProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -16,13 +16,10 @@
package org.springframework.boot.context.embedded;
import org.apache.catalina.Context;
import org.apache.tomcat.util.http.LegacyCookieProcessor;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizer;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -34,33 +31,16 @@ import org.springframework.context.annotation.Configuration;
public class TomcatLegacyCookieProcessorExample {
/**
* Configuration class that declares the required
* {@link ServletWebServerFactoryCustomizer}.
* Configuration class that declares the required {@link WebServerFactoryCustomizer}.
*/
@Configuration
static class LegacyCookieProcessorConfiguration {
// tag::customizer[]
@Bean
public ServletWebServerFactoryCustomizer cookieProcessorCustomizer() {
return new ServletWebServerFactoryCustomizer() {
@Override
public void customize(ConfigurableServletWebServerFactory serverFactory) {
if (serverFactory instanceof TomcatServletWebServerFactory) {
((TomcatServletWebServerFactory) serverFactory)
.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
context.setCookieProcessor(new LegacyCookieProcessor());
}
});
}
}
};
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieProcessorCustomizer() {
return (serverFactory) -> serverFactory.addContextCustomizers(
(context) -> context.setCookieProcessor(new LegacyCookieProcessor()));
}
// end::customizer[]

View File

@@ -24,8 +24,8 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.embedded.TomcatLegacyCookieProcessorExample.LegacyCookieProcessorConfiguration;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactoryCustomizerBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -42,8 +42,8 @@ public class TomcatLegacyCookieProcessorExampleTests {
public void cookieProcessorIsCustomized() {
ServletWebServerApplicationContext applicationContext = (ServletWebServerApplicationContext) new SpringApplication(
TestConfiguration.class, LegacyCookieProcessorConfiguration.class).run();
Context context = (Context) ((TomcatWebServer) applicationContext
.getWebServer()).getTomcat().getHost().findChildren()[0];
Context context = (Context) ((TomcatWebServer) applicationContext.getWebServer())
.getTomcat().getHost().findChildren()[0];
assertThat(context.getCookieProcessor())
.isInstanceOf(LegacyCookieProcessor.class);
}
@@ -57,8 +57,8 @@ public class TomcatLegacyCookieProcessorExampleTests {
}
@Bean
public ServletWebServerFactoryCustomizerBeanPostProcessor postProcessor() {
return new ServletWebServerFactoryCustomizerBeanPostProcessor();
public WebServerFactoryCustomizerBeanPostProcessor postProcessor() {
return new WebServerFactoryCustomizerBeanPostProcessor();
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright 2012-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.boot.web.reactive.server;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
/**
* {@link BeanPostProcessor} that applies all {@link ReactiveWebServerCustomizer}s from
* the bean factory to {@link ConfigurableReactiveWebServerFactory} beans.
*
* @author Brian Clozel
* @author Stephane Nicoll
* @since 2.0.0
*/
public class ReactiveWebServerCustomizerBeanPostProcessor
implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<ReactiveWebServerCustomizer> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ConfigurableReactiveWebServerFactory) {
postProcessBeforeInitialization((ConfigurableReactiveWebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
private void postProcessBeforeInitialization(ConfigurableReactiveWebServerFactory bean) {
for (ReactiveWebServerCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<ReactiveWebServerCustomizer> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(this.beanFactory
.getBeansOfType(ReactiveWebServerCustomizer.class, false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
}

View File

@@ -20,12 +20,14 @@ import java.net.InetAddress;
import java.util.Set;
/**
* Simple interface that represents customizations to an web server factory.
* Simple interface that represents customizations to a {@link WebServerFactory}.
*
* @author Phillip Webb
* @author Brian Clozel
* @since 2.0.0
*/
public interface ConfigurableWebServerFactory extends ErrorPageRegistry {
public interface ConfigurableWebServerFactory
extends WebServerFactory, ErrorPageRegistry {
/**
* Sets the port that the web server should listen on. If not specified port '8080'

View File

@@ -14,21 +14,17 @@
* limitations under the License.
*/
package org.springframework.boot.web.reactive.server;
package org.springframework.boot.web.server;
/**
* Strategy interface for customizing auto-configured reactive web servers. Any beans of
* this type will get a callback with the server factory before the server itself is
* started, so you can set the port, address, error pages etc.
* @author Brian Clozel
* Tagging interface for factories that create a {@link WebServer}.
*
* @author Phillip Webb
* @since 2.0.0
* @see WebServer
* @see org.springframework.boot.web.servlet.server.ServletWebServerFactory
* @see org.springframework.boot.web.reactive.server.ReactiveWebServerFactory
*/
@FunctionalInterface
public interface ReactiveWebServerCustomizer {
public interface WebServerFactory {
/**
* Customize the specified {@link ConfigurableReactiveWebServerFactory}.
* @param server the server to customize
*/
void customize(ConfigurableReactiveWebServerFactory server);
}

View File

@@ -14,32 +14,34 @@
* limitations under the License.
*/
package org.springframework.boot.web.servlet.server;
package org.springframework.boot.web.server;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* Strategy interface for customizing auto-configured web server factory. Any beans of
* this type will get a callback with the server factory before the server itself is
* started, so you can set the port, address, error pages etc.
* Strategy interface for customizing {@link WebServerFactory web server factories}. Any
* beans of this type will get a callback with the server factory before the server itself
* is started, so you can set the port, address, error pages etc.
* <p>
* Beware: calls to this interface are usually made from a
* {@link ServletWebServerFactoryCustomizerBeanPostProcessor} which is a
* {@link WebServerFactoryCustomizerBeanPostProcessor} which is a
* {@link BeanPostProcessor} (so called very early in the ApplicationContext lifecycle).
* It might be safer to lookup dependencies lazily in the enclosing BeanFactory rather
* than injecting them with {@code @Autowired}.
*
* @param <T> The configurable web server factory
* @author Phillip Webb
* @author Dave Syer
* @author Brian Clozel
* @since 2.0.0
* @see ServletWebServerFactoryCustomizerBeanPostProcessor
* @see WebServerFactoryCustomizerBeanPostProcessor
*/
@FunctionalInterface
public interface ServletWebServerFactoryCustomizer {
public interface WebServerFactoryCustomizer<T extends WebServerFactory> {
/**
* Customize the specified {@link ConfigurableServletWebServerFactory}.
* @param serverFactory the server factory to customize
* Customize the specified {@link WebServerFactory}.
* @param server the server to customize
*/
void customize(ConfigurableServletWebServerFactory serverFactory);
void customize(T server);
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright 2012-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.boot.web.server;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.util.Assert;
/**
* {@link BeanPostProcessor} that applies all {@link WebServerFactoryCustomizer} beans
* from the bean factory to {@link WebServerFactory} beans.
*
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @since 2.0.0
*/
public class WebServerFactoryCustomizerBeanPostProcessor
implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<WebServerFactoryCustomizer<?>> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"WebServerCustomizerBeanPostProcessor can only be used "
+ "with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof WebServerFactory) {
postProcessBeforeInitialization((WebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
private void postProcessBeforeInitialization(WebServerFactory bean) {
for (WebServerFactoryCustomizer<?> customizer : getCustomizers()) {
Class<?> type = ResolvableType
.forClass(WebServerFactoryCustomizer.class, customizer.getClass())
.getGeneric().resolve(WebServerFactory.class);
if (type.isInstance(bean)) {
invokeCustomizer(customizer, bean);
}
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void invokeCustomizer(WebServerFactoryCustomizer customizer,
WebServerFactory webServerFactory) {
try {
customizer.customize(webServerFactory);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || msg.startsWith(webServerFactory.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the
// generic event type for
logLambdaDebug(customizer, ex);
}
else {
throw ex;
}
}
}
private void logLambdaDebug(WebServerFactoryCustomizer<?> customizer,
ClassCastException ex) {
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching factory type for customizer: " + customizer, ex);
}
}
private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(getWebServerFactoryCustomizerBeans());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
return (Collection) this.beanFactory
.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
}
}

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.MimeMappings;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
/**
@@ -37,7 +38,7 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
* @author Brian Clozel
* @since 2.0.0
* @see ServletWebServerFactory
* @see ServletWebServerFactoryCustomizer
* @see WebServerFactoryCustomizer
*/
public interface ConfigurableServletWebServerFactory
extends ConfigurableWebServerFactory {

View File

@@ -1,90 +0,0 @@
/*
* Copyright 2012-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.boot.web.servlet.server;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.util.Assert;
/**
* {@link BeanPostProcessor} that applies all {@link ServletWebServerFactoryCustomizer}s
* from the bean factory to {@link ConfigurableServletWebServerFactory} beans.
*
* @author Dave Syer
* @author Phillip Webb
* @author Stephane Nicoll
* @since 2.0.0
*/
public class ServletWebServerFactoryCustomizerBeanPostProcessor
implements BeanPostProcessor, BeanFactoryAware {
private ListableBeanFactory beanFactory;
private List<ServletWebServerFactoryCustomizer> customizers;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory,
"ServletWebServerFactoryCustomizerBeanPostProcessor can only be used "
+ "with a ListableBeanFactory");
this.beanFactory = (ListableBeanFactory) beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ConfigurableServletWebServerFactory) {
postProcessBeforeInitialization((ConfigurableServletWebServerFactory) bean);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
private void postProcessBeforeInitialization(
ConfigurableServletWebServerFactory bean) {
for (ServletWebServerFactoryCustomizer customizer : getCustomizers()) {
customizer.customize(bean);
}
}
private Collection<ServletWebServerFactoryCustomizer> getCustomizers() {
if (this.customizers == null) {
// Look up does not include the parent context
this.customizers = new ArrayList<>(this.beanFactory
.getBeansOfType(ServletWebServerFactoryCustomizer.class, false, false)
.values());
Collections.sort(this.customizers, AnnotationAwareOrderComparator.INSTANCE);
this.customizers = Collections.unmodifiableList(this.customizers);
}
return this.customizers;
}
}

View File

@@ -0,0 +1,217 @@
/*
* Copyright 2012-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.boot.web.server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link WebServerFactoryCustomizerBeanPostProcessor}.
*
* @author Phillip Webb
*/
public class WebServerFactoryCustomizerBeanPostProcessorTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private WebServerFactoryCustomizerBeanPostProcessor processor = new WebServerFactoryCustomizerBeanPostProcessor();
@Mock
private ListableBeanFactory beanFactory;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.processor.setBeanFactory(this.beanFactory);
}
@Test
public void setBeanFactoryWhenNotListableShouldThrowException() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("WebServerCustomizerBeanPostProcessor can only "
+ "be used with a ListableBeanFactory");
this.processor.setBeanFactory(mock(BeanFactory.class));
}
@Test
public void postProcessBeforeShouldReturnBean() throws Exception {
addMockBeans(Collections.emptyMap());
Object bean = new Object();
Object result = this.processor.postProcessBeforeInitialization(bean, "foo");
assertThat(result).isSameAs(bean);
}
@Test
public void postProcessAfterShouldReturnBean() throws Exception {
addMockBeans(Collections.emptyMap());
Object bean = new Object();
Object result = this.processor.postProcessAfterInitialization(bean, "foo");
assertThat(result).isSameAs(bean);
}
@Test
public void postProcessAfterShouldCallInterfaceCustomizers() throws Exception {
Map<String, Object> beans = addInterfaceBeans();
addMockBeans(beans);
postProcessBeforeInitialization(WebServerFactory.class);
assertThat(wasCalled(beans, "one")).isFalse();
assertThat(wasCalled(beans, "two")).isFalse();
assertThat(wasCalled(beans, "all")).isTrue();
}
@Test
public void postProcessAfterWhenWebServerFactoryOneShouldCallInterfaceCustomizers()
throws Exception {
Map<String, Object> beans = addInterfaceBeans();
addMockBeans(beans);
postProcessBeforeInitialization(WebServerFactoryOne.class);
assertThat(wasCalled(beans, "one")).isTrue();
assertThat(wasCalled(beans, "two")).isFalse();
assertThat(wasCalled(beans, "all")).isTrue();
}
@Test
public void postProcessAfterWhenWebServerFactoryTwoShouldCallInterfaceCustomizers()
throws Exception {
Map<String, Object> beans = addInterfaceBeans();
addMockBeans(beans);
postProcessBeforeInitialization(WebServerFactoryTwo.class);
assertThat(wasCalled(beans, "one")).isFalse();
assertThat(wasCalled(beans, "two")).isTrue();
assertThat(wasCalled(beans, "all")).isTrue();
}
private Map<String, Object> addInterfaceBeans() {
WebServerFactoryOneCustomizer oneCustomizer = new WebServerFactoryOneCustomizer();
WebServerFactoryTwoCustomizer twoCustomizer = new WebServerFactoryTwoCustomizer();
WebServerFactoryAllCustomizer allCustomizer = new WebServerFactoryAllCustomizer();
Map<String, Object> beans = new LinkedHashMap<>();
beans.put("one", oneCustomizer);
beans.put("two", twoCustomizer);
beans.put("all", allCustomizer);
return beans;
}
@Test
public void postProcessAfterShouldCallLambdaCustomizers() throws Exception {
List<String> called = new ArrayList<>();
addLambdaBeans(called);
postProcessBeforeInitialization(WebServerFactory.class);
assertThat(called).containsExactly("all");
}
@Test
public void postProcessAfterWhenWebServerFactoryOneShouldCallLambdaCustomizers()
throws Exception {
List<String> called = new ArrayList<>();
addLambdaBeans(called);
postProcessBeforeInitialization(WebServerFactoryOne.class);
assertThat(called).containsExactly("one", "all");
}
@Test
public void postProcessAfterWhenWebServerFactoryTwoShouldCallLambdaCustomizers()
throws Exception {
List<String> called = new ArrayList<>();
addLambdaBeans(called);
postProcessBeforeInitialization(WebServerFactoryTwo.class);
assertThat(called).containsExactly("two", "all");
}
private void addLambdaBeans(List<String> called) {
WebServerFactoryCustomizer<WebServerFactoryOne> one = (f) -> called.add("one");
WebServerFactoryCustomizer<WebServerFactoryTwo> two = (f) -> called.add("two");
WebServerFactoryCustomizer<WebServerFactory> all = (f) -> called.add("all");
Map<String, Object> beans = new LinkedHashMap<String, Object>();
beans.put("one", one);
beans.put("two", two);
beans.put("all", all);
addMockBeans(beans);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private void addMockBeans(Map<String, ?> beans) {
given(this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false,
false)).willReturn((Map<String, WebServerFactoryCustomizer>) beans);
}
private void postProcessBeforeInitialization(Class<?> type) {
this.processor.postProcessBeforeInitialization(mock(type), "foo");
}
private boolean wasCalled(Map<String, ?> beans, String name) {
return ((MockWebServerFactoryCustomizer<?>) beans.get(name)).wasCalled();
}
private interface WebServerFactoryOne extends WebServerFactory {
}
private interface WebServerFactoryTwo extends WebServerFactory {
}
private static class MockWebServerFactoryCustomizer<T extends WebServerFactory>
implements WebServerFactoryCustomizer<T> {
private boolean called;
@Override
public void customize(T server) {
this.called = true;
}
public boolean wasCalled() {
return this.called;
}
}
private static class WebServerFactoryOneCustomizer
extends MockWebServerFactoryCustomizer<WebServerFactoryOne> {
}
private static class WebServerFactoryTwoCustomizer
extends MockWebServerFactoryCustomizer<WebServerFactoryTwo> {
}
private static class WebServerFactoryAllCustomizer
extends MockWebServerFactoryCustomizer<WebServerFactory> {
}
}