mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
[bs-115] Add EmbeddedServletContainerCustomizer as a callback
* All instances are called before the container is started in a bean post processor * Users still have to be careful because the customizer is called very early in the ApplicationContext lifecycle (e.g. might have to do a lookup for some dependencies instead of @Autowired) [Fixes #49671463] User-hook for customizing embedded servlet container
This commit is contained in:
parent
56865ab260
commit
ef5c8aa304
@ -25,6 +25,7 @@ import org.springframework.bootstrap.actuate.error.ErrorEndpoint;
|
||||
import org.springframework.bootstrap.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnBean;
|
||||
import org.springframework.bootstrap.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.ErrorPage;
|
||||
import org.springframework.bootstrap.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
@ -100,7 +101,7 @@ public class ManagementServerConfiguration implements BeanPostProcessor {
|
||||
if (bean instanceof AbstractEmbeddedServletContainerFactory
|
||||
&& !this.initialized) {
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = (AbstractEmbeddedServletContainerFactory) bean;
|
||||
ConfigurableEmbeddedServletContainerFactory factory = (ConfigurableEmbeddedServletContainerFactory) bean;
|
||||
factory.setPort(this.configuration.getPort());
|
||||
factory.setAddress(this.configuration.getAddress());
|
||||
factory.setContextPath(this.configuration.getContextPath());
|
||||
|
@ -20,17 +20,15 @@ import javax.servlet.Servlet;
|
||||
|
||||
import org.apache.catalina.valves.AccessLogValve;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.bootstrap.actuate.error.ErrorEndpoint;
|
||||
import org.springframework.bootstrap.actuate.properties.ServerProperties;
|
||||
import org.springframework.bootstrap.actuate.properties.ServerProperties.Tomcat;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.bootstrap.context.embedded.ErrorPage;
|
||||
import org.springframework.bootstrap.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -50,66 +48,34 @@ import org.springframework.util.StringUtils;
|
||||
@ConditionalOnClass({ Servlet.class })
|
||||
@Order(Integer.MIN_VALUE)
|
||||
@Import(InfoConfiguration.class)
|
||||
public class ServerConfiguration implements BeanPostProcessor, BeanFactoryAware {
|
||||
public class ServerConfiguration implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Autowired
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
// Don't do this! We don't get a callback for our own dependencies (lifecycle).
|
||||
// @Autowired
|
||||
// private AbstractEmbeddedServletContainerFactory factory;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
@Value("${endpoints.error.path:/error}")
|
||||
private String errorPath = "/error";
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ErrorEndpoint errorEndpoint() {
|
||||
return new ErrorEndpoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
// Need to do a look up here to make it lazy
|
||||
ServerProperties server = this.beanFactory.getBean(ServerProperties.class);
|
||||
|
||||
if (bean instanceof EmbeddedServletContainerFactory) {
|
||||
|
||||
if (bean instanceof AbstractEmbeddedServletContainerFactory
|
||||
&& !this.initialized) {
|
||||
|
||||
// Cannot use @Autowired because the injection happens too early
|
||||
ServerProperties server = this.beanFactory
|
||||
.getBean(ServerProperties.class);
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = (AbstractEmbeddedServletContainerFactory) bean;
|
||||
factory.setPort(server.getPort());
|
||||
factory.setAddress(server.getAddress());
|
||||
factory.setContextPath(server.getContextPath());
|
||||
|
||||
if (factory instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
configureTomcat((TomcatEmbeddedServletContainerFactory) factory,
|
||||
server);
|
||||
}
|
||||
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
this.initialized = true;
|
||||
|
||||
}
|
||||
factory.setPort(server.getPort());
|
||||
factory.setAddress(server.getAddress());
|
||||
factory.setContextPath(server.getContextPath());
|
||||
|
||||
if (factory instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
configureTomcat((TomcatEmbeddedServletContainerFactory) factory, server);
|
||||
}
|
||||
|
||||
return bean;
|
||||
factory.addErrorPages(new ErrorPage(this.errorPath));
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.bootstrap.autoconfigure.web;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnClass;
|
||||
import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.bootstrap.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
||||
* {@link JettyEmbeddedServletContainerFactory}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ Servlet.class })
|
||||
public class EmbeddedContainerCustomizerConfiguration {
|
||||
|
||||
@Autowired(required = false)
|
||||
private Set<EmbeddedServletContainerCustomizer> customizers = new HashSet<EmbeddedServletContainerCustomizer>();
|
||||
|
||||
@Bean
|
||||
public BeanPostProcessor embeddedContainerCustomizerBeanPostProcessor() {
|
||||
return new EmbeddedContainerCustomizerBeanPostProcessor(this.customizers);
|
||||
}
|
||||
|
||||
private static final class EmbeddedContainerCustomizerBeanPostProcessor implements
|
||||
BeanPostProcessor {
|
||||
|
||||
private List<EmbeddedServletContainerCustomizer> customizers;
|
||||
|
||||
public EmbeddedContainerCustomizerBeanPostProcessor(
|
||||
Set<EmbeddedServletContainerCustomizer> customizers) {
|
||||
final List<EmbeddedServletContainerCustomizer> list = new ArrayList<EmbeddedServletContainerCustomizer>(
|
||||
customizers);
|
||||
Collections.sort(list, new AnnotationAwareOrderComparator());
|
||||
this.customizers = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof ConfigurableEmbeddedServletContainerFactory) {
|
||||
ConfigurableEmbeddedServletContainerFactory factory = (ConfigurableEmbeddedServletContainerFactory) bean;
|
||||
for (EmbeddedServletContainerCustomizer customizer : this.customizers) {
|
||||
customizer.customize(factory);
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,7 @@ import org.springframework.util.Assert;
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
EmbeddedServletContainerFactory {
|
||||
ConfigurableEmbeddedServletContainerFactory {
|
||||
|
||||
private final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
@ -170,6 +170,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* @see #setInitializers
|
||||
* @see #getInitializers
|
||||
*/
|
||||
@Override
|
||||
public void addInitializers(ServletContextInitializer... initializers) {
|
||||
Assert.notNull(initializers, "Initializers must not be null");
|
||||
this.initializers.addAll(Arrays.asList(initializers));
|
||||
@ -181,6 +182,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* parameters.
|
||||
* @return the initializers
|
||||
*/
|
||||
@Override
|
||||
public List<ServletContextInitializer> getInitializers() {
|
||||
return this.initializers;
|
||||
}
|
||||
@ -190,6 +192,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* files.
|
||||
* @param documentRoot the document root or {@code null} if not required
|
||||
*/
|
||||
@Override
|
||||
public void setDocumentRoot(File documentRoot) {
|
||||
this.documentRoot = documentRoot;
|
||||
}
|
||||
@ -198,6 +201,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* Returns the document root which will be used by the web context to serve static
|
||||
* files.
|
||||
*/
|
||||
@Override
|
||||
public File getDocumentRoot() {
|
||||
return this.documentRoot;
|
||||
}
|
||||
@ -206,6 +210,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* Sets the error pages that will be used when handling exceptions.
|
||||
* @param errorPages the error pages
|
||||
*/
|
||||
@Override
|
||||
public void setErrorPages(Set<ErrorPage> errorPages) {
|
||||
Assert.notNull(errorPages, "ErrorPages must not be null");
|
||||
this.errorPages = new LinkedHashSet<ErrorPage>(errorPages);
|
||||
@ -215,6 +220,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* Adds error pages that will be used when handling exceptions.
|
||||
* @param errorPages the error pages
|
||||
*/
|
||||
@Override
|
||||
public void addErrorPages(ErrorPage... errorPages) {
|
||||
Assert.notNull(this.initializers, "ErrorPages must not be null");
|
||||
this.errorPages.addAll(Arrays.asList(errorPages));
|
||||
@ -224,6 +230,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* Returns a mutable set of {@link ErrorPage}s that will be used when handling
|
||||
* exceptions.
|
||||
*/
|
||||
@Override
|
||||
public Set<ErrorPage> getErrorPages() {
|
||||
return this.errorPages;
|
||||
}
|
||||
@ -233,6 +240,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* files from the {@link #setDocumentRoot(File) document root} will be served.
|
||||
* @param registerDefaultServlet if the default servlet should be registered
|
||||
*/
|
||||
@Override
|
||||
public void setRegisterDefaultServlet(boolean registerDefaultServlet) {
|
||||
this.registerDefaultServlet = registerDefaultServlet;
|
||||
}
|
||||
@ -243,7 +251,8 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
*
|
||||
* @return true if the JSP servlet is to be registered
|
||||
*/
|
||||
protected boolean getRegisterJspServlet() {
|
||||
@Override
|
||||
public boolean isRegisterJspServlet() {
|
||||
return this.registerJspServlet;
|
||||
}
|
||||
|
||||
@ -253,6 +262,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
* will be served.
|
||||
* @param registerJspServlet if the JSP servlet should be registered
|
||||
*/
|
||||
@Override
|
||||
public void setRegisterJspServlet(boolean registerJspServlet) {
|
||||
this.registerJspServlet = registerJspServlet;
|
||||
}
|
||||
@ -262,7 +272,8 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
*
|
||||
* @return true if the default servlet is to be registered
|
||||
*/
|
||||
protected boolean getRegisterDefaultServlet() {
|
||||
@Override
|
||||
public boolean isRegisterDefaultServlet() {
|
||||
return this.registerDefaultServlet;
|
||||
}
|
||||
|
||||
@ -275,6 +286,7 @@ public abstract class AbstractEmbeddedServletContainerFactory implements
|
||||
*
|
||||
* @param jspServletClassName the class name for the JSP servlet if used
|
||||
*/
|
||||
@Override
|
||||
public void setJspServletClassName(String jspServletClassName) {
|
||||
this.jspServletClassName = jspServletClassName;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.bootstrap.context.embedded;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
@ -55,6 +56,10 @@ public class AnnotationConfigEmbeddedWebApplicationContext extends
|
||||
|
||||
private final ClassPathBeanDefinitionScanner scanner;
|
||||
|
||||
private Class<?>[] annotatedClasses;
|
||||
|
||||
private String[] basePackages;
|
||||
|
||||
/**
|
||||
* Create a new {@link AnnotationConfigEmbeddedWebApplicationContext} that needs to be
|
||||
* populated through {@link #register} calls and then manually {@linkplain #refresh
|
||||
@ -149,9 +154,9 @@ public class AnnotationConfigEmbeddedWebApplicationContext extends
|
||||
* @see #refresh()
|
||||
*/
|
||||
public void register(Class<?>... annotatedClasses) {
|
||||
this.annotatedClasses = annotatedClasses;
|
||||
Assert.notEmpty(annotatedClasses,
|
||||
"At least one annotated class must be specified");
|
||||
this.reader.register(annotatedClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -162,8 +167,8 @@ public class AnnotationConfigEmbeddedWebApplicationContext extends
|
||||
* @see #refresh()
|
||||
*/
|
||||
public void scan(String... basePackages) {
|
||||
this.basePackages = basePackages;
|
||||
Assert.notEmpty(basePackages, "At least one base package must be specified");
|
||||
this.scanner.scan(basePackages);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -172,4 +177,15 @@ public class AnnotationConfigEmbeddedWebApplicationContext extends
|
||||
super.prepareRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
super.postProcessBeanFactory(beanFactory);
|
||||
if (this.basePackages != null && this.basePackages.length > 0) {
|
||||
this.scanner.scan(this.basePackages);
|
||||
}
|
||||
if (this.annotatedClasses != null && this.annotatedClasses.length > 0) {
|
||||
this.reader.register(this.annotatedClasses);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.bootstrap.context.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Simple interface that represents customizations to an
|
||||
* {@link EmbeddedServletContainerFactory}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @see EmbeddedServletContainerFactory
|
||||
*/
|
||||
public interface ConfigurableEmbeddedServletContainerFactory extends
|
||||
EmbeddedServletContainerFactory {
|
||||
|
||||
void setContextPath(String contextPath);
|
||||
|
||||
String getContextPath();
|
||||
|
||||
void setPort(int port);
|
||||
|
||||
int getPort();
|
||||
|
||||
void setAddress(InetAddress address);
|
||||
|
||||
InetAddress getAddress();
|
||||
|
||||
void setInitializers(List<? extends ServletContextInitializer> initializers);
|
||||
|
||||
void setJspServletClassName(String jspServletClassName);
|
||||
|
||||
boolean isRegisterDefaultServlet();
|
||||
|
||||
void setRegisterJspServlet(boolean registerJspServlet);
|
||||
|
||||
boolean isRegisterJspServlet();
|
||||
|
||||
void setRegisterDefaultServlet(boolean registerDefaultServlet);
|
||||
|
||||
Set<ErrorPage> getErrorPages();
|
||||
|
||||
void addErrorPages(ErrorPage... errorPages);
|
||||
|
||||
void setErrorPages(Set<ErrorPage> errorPages);
|
||||
|
||||
File getDocumentRoot();
|
||||
|
||||
void setDocumentRoot(File documentRoot);
|
||||
|
||||
List<ServletContextInitializer> getInitializers();
|
||||
|
||||
void addInitializers(ServletContextInitializer... initializers);
|
||||
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
package org.springframework.bootstrap.context.embedded;
|
||||
|
||||
/**
|
||||
* Simple interface that represents a fully configure embedded servlet container (for
|
||||
* Simple interface that represents a fully configured embedded servlet container (for
|
||||
* example Tomcat or Jetty). Allows the container to be {@link #stop() stopped}.
|
||||
*
|
||||
* <p>
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.bootstrap.context.embedded;
|
||||
|
||||
/**
|
||||
* Strategy interface for customizing auto-configured embedded servlet containers. Any
|
||||
* beans of this type will get a callback with the container factory before the container
|
||||
* itself is started, so you can set the port, address, error pages etc. Beware: will be
|
||||
* called from a BeanPostProcessor (so very early in the ApplicationContext lifecycle), so
|
||||
* it might be safer to lookup dependencies lazily in the enclosing BeanFactory rather
|
||||
* than injecting them with <code>@Autowired</code>.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface EmbeddedServletContainerCustomizer {
|
||||
|
||||
void customize(ConfigurableEmbeddedServletContainerFactory factory);
|
||||
|
||||
}
|
@ -110,10 +110,10 @@ public class JettyEmbeddedServletContainerFactory extends
|
||||
this.context.setContextPath(StringUtils.hasLength(contextPath) ? contextPath
|
||||
: "/");
|
||||
configureDocumentRoot(this.context);
|
||||
if (getRegisterDefaultServlet()) {
|
||||
if (isRegisterDefaultServlet()) {
|
||||
addDefaultServlet(this.context);
|
||||
}
|
||||
if (getRegisterJspServlet()
|
||||
if (isRegisterJspServlet()
|
||||
&& ClassUtils.isPresent(getJspServletClassName(), getClass()
|
||||
.getClassLoader())) {
|
||||
addJspServlet(this.context);
|
||||
|
@ -144,10 +144,10 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||
if (this.resourceLoader != null) {
|
||||
context.setParentClassLoader(this.resourceLoader.getClassLoader());
|
||||
}
|
||||
if (getRegisterDefaultServlet()) {
|
||||
if (isRegisterDefaultServlet()) {
|
||||
addDefaultServlet(context);
|
||||
}
|
||||
if (getRegisterJspServlet()
|
||||
if (isRegisterJspServlet()
|
||||
&& ClassUtils.isPresent(getJspServletClassName(), getClass()
|
||||
.getClassLoader())) {
|
||||
addJspServlet(context);
|
||||
|
@ -4,6 +4,7 @@ org.springframework.bootstrap.autoconfigure.data.JpaRepositoriesAutoConfiguratio
|
||||
org.springframework.bootstrap.autoconfigure.jdbc.EmbeddedDatabaseAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.batch.BatchAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedContainerCustomizerConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedJettyAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.EmbeddedTomcatAutoConfiguration,\
|
||||
org.springframework.bootstrap.autoconfigure.web.WebMvcAutoConfiguration
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.bootstrap.autoconfigure.web;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.bootstrap.context.annotation.ConditionalOnExpression;
|
||||
import org.springframework.bootstrap.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.bootstrap.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.bootstrap.context.embedded.MockEmbeddedServletContainerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class WebMvcAutoConfigurationTests {
|
||||
|
||||
private AnnotationConfigEmbeddedWebApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void createFromConfigClass() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext(
|
||||
WebMvcAutoConfiguration.class, EmbeddedContainerConfiguration.class);
|
||||
verifyContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containerHasNoServletContext() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext(
|
||||
WebMvcAutoConfiguration.class, EmbeddedContainerConfiguration.class,
|
||||
EnsureContainerHasNoServletContext.class);
|
||||
verifyContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void customizeContainerThroughCallback() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext(
|
||||
WebMvcAutoConfiguration.class, EmbeddedContainerConfiguration.class,
|
||||
EmbeddedContainerCustomizerConfiguration.class,
|
||||
CallbackEmbeddedContainerCustomizer.class);
|
||||
verifyContext();
|
||||
assertEquals(9000, getContainerFactory().getPort());
|
||||
}
|
||||
|
||||
private void verifyContext() {
|
||||
MockEmbeddedServletContainerFactory containerFactory = getContainerFactory();
|
||||
Servlet servlet = this.context.getBean(Servlet.class);
|
||||
verify(containerFactory.getServletContext()).addServlet("dispatcherServlet",
|
||||
servlet);
|
||||
}
|
||||
|
||||
private MockEmbeddedServletContainerFactory getContainerFactory() {
|
||||
return this.context.getBean(MockEmbeddedServletContainerFactory.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnExpression("true")
|
||||
public static class EmbeddedContainerConfiguration {
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory containerFactory() {
|
||||
return new MockEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class EnsureContainerHasNoServletContext implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof ConfigurableEmbeddedServletContainerFactory) {
|
||||
MockEmbeddedServletContainerFactory containerFactory = (MockEmbeddedServletContainerFactory) bean;
|
||||
assertNull(containerFactory.getServletContext());
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class CallbackEmbeddedContainerCustomizer implements
|
||||
EmbeddedServletContainerCustomizer {
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
|
||||
factory.setPort(9000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -79,7 +79,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void startServlet() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
assertThat(getResponse("http://localhost:8080/hello"), equalTo("Hello World"));
|
||||
@ -87,7 +87,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void emptyServer() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setPort(0);
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
@ -98,7 +98,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void stopServlet() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
this.container.stop();
|
||||
@ -109,7 +109,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
@Test
|
||||
@Ignore
|
||||
public void restartWithKeepAlive() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
|
||||
@ -130,7 +130,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void startServletAndFilter() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory.getEmbdeddedServletContainer(
|
||||
exampleServletRegistration(), new FilterRegistrationBean(
|
||||
new ExampleFilter()));
|
||||
@ -140,7 +140,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
@Test
|
||||
public void startBlocksUntilReadyToServe() throws Exception {
|
||||
// FIXME Assume.group(TestGroup.LONG_RUNNING);
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
final Date[] date = new Date[1];
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(new ServletContextInitializer() {
|
||||
@ -160,7 +160,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void specificPort() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setPort(8081);
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
@ -169,7 +169,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void specificContextRoot() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setContextPath("/say");
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
@ -200,7 +200,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void doubleStop() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
this.container = factory
|
||||
.getEmbdeddedServletContainer(exampleServletRegistration());
|
||||
this.container.stop();
|
||||
@ -209,7 +209,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@Test
|
||||
public void multipleConfigurations() throws Exception {
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
ConfigurableEmbeddedServletContainerFactory factory = getFactory();
|
||||
ServletContextInitializer[] initializers = new ServletContextInitializer[6];
|
||||
for (int i = 0; i < initializers.length; i++) {
|
||||
initializers[i] = mock(ServletContextInitializer.class);
|
||||
|
@ -17,12 +17,18 @@
|
||||
package org.springframework.bootstrap.context.embedded;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.bootstrap.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.bootstrap.context.embedded.config.ExampleEmbeddedWebApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Tests for {@link AnnotationConfigEmbeddedWebApplicationContext}.
|
||||
@ -64,10 +70,95 @@ public class AnnotationConfigEmbeddedWebApplicationContextTests {
|
||||
verifyContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndInitializeCyclic() throws Exception {
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext(
|
||||
ServletContextAwareEmbeddedConfiguration.class);
|
||||
verifyContext();
|
||||
// You can't initialize the application context and inject the servlet context
|
||||
// because of a cycle - we'd like this to be not null but it never will be
|
||||
assertNull(this.context.getBean(ServletContextAwareEmbeddedConfiguration.class)
|
||||
.getServletContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAndInitializeWithRoot() throws Exception {
|
||||
AnnotationConfigEmbeddedWebApplicationContext parent = new AnnotationConfigEmbeddedWebApplicationContext(
|
||||
EmbeddedContainerConfiguration.class);
|
||||
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
|
||||
this.context.register(ServletContextAwareConfiguration.class);
|
||||
this.context.setParent(parent);
|
||||
this.context.setServletContext(parent.getServletContext());
|
||||
this.context.refresh();
|
||||
verifyContext();
|
||||
assertNotNull(this.context.getBean(ServletContextAwareConfiguration.class)
|
||||
.getServletContext());
|
||||
}
|
||||
|
||||
private void verifyContext() {
|
||||
MockEmbeddedServletContainerFactory containerFactory = this.context
|
||||
.getBean(MockEmbeddedServletContainerFactory.class);
|
||||
Servlet servlet = this.context.getBean(Servlet.class);
|
||||
verify(containerFactory.getServletContext()).addServlet("servlet", servlet);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public static class ServletContextAwareEmbeddedConfiguration implements
|
||||
ServletContextAware {
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory containerFactory() {
|
||||
return new MockEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Servlet servlet() {
|
||||
return new MockServlet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class EmbeddedContainerConfiguration {
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerFactory containerFactory() {
|
||||
return new MockEmbeddedServletContainerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public static class ServletContextAwareConfiguration implements ServletContextAware {
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
@Bean
|
||||
public Servlet servlet() {
|
||||
return new MockServlet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,6 @@
|
||||
|
||||
package org.springframework.bootstrap.context.embedded;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
@ -29,6 +23,7 @@ import java.util.NoSuchElementException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
@ -36,25 +31,27 @@ import javax.servlet.ServletRegistration;
|
||||
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.bootstrap.context.embedded.EmbeddedServletContainerFactory;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Matchers.anyObject;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
/**
|
||||
* Mock {@link EmbeddedServletContainerFactory}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class MockEmbeddedServletContainerFactory implements
|
||||
EmbeddedServletContainerFactory {
|
||||
public class MockEmbeddedServletContainerFactory extends
|
||||
AbstractEmbeddedServletContainerFactory {
|
||||
|
||||
private MockEmbeddedServletContainer container;
|
||||
|
||||
private int port;
|
||||
|
||||
@Override
|
||||
public EmbeddedServletContainer getEmbdeddedServletContainer(
|
||||
ServletContextInitializer... initializers) {
|
||||
this.container = spy(new MockEmbeddedServletContainer(initializers, port));
|
||||
this.container = spy(new MockEmbeddedServletContainer(initializers, getPort()));
|
||||
return this.container;
|
||||
}
|
||||
|
||||
@ -63,19 +60,17 @@ public class MockEmbeddedServletContainerFactory implements
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return getContainer().servletContext;
|
||||
return getContainer() == null ? null : getContainer().servletContext;
|
||||
}
|
||||
|
||||
public RegisteredServlet getRegisteredServlet(int index) {
|
||||
return getContainer().getRegisteredServlets().get(index);
|
||||
return getContainer() == null ? null : getContainer().getRegisteredServlets()
|
||||
.get(index);
|
||||
}
|
||||
|
||||
public RegisteredFilter getRegisteredFilter(int index) {
|
||||
return getContainer().getRegisteredFilters().get(index);
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
return getContainer() == null ? null : getContainer().getRegisteredFilters().get(
|
||||
index);
|
||||
}
|
||||
|
||||
public static class MockEmbeddedServletContainer implements EmbeddedServletContainer {
|
||||
@ -128,6 +123,8 @@ public class MockEmbeddedServletContainerFactory implements
|
||||
MockEmbeddedServletContainer.<String> emptyEnumeration());
|
||||
given(this.servletContext.getAttributeNames()).willReturn(
|
||||
MockEmbeddedServletContainer.<String> emptyEnumeration());
|
||||
given(this.servletContext.getNamedDispatcher("default")).willReturn(
|
||||
mock(RequestDispatcher.class));
|
||||
for (ServletContextInitializer initializer : this.initializers) {
|
||||
initializer.onStartup(this.servletContext);
|
||||
}
|
||||
@ -178,7 +175,7 @@ public class MockEmbeddedServletContainerFactory implements
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
return this.port;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.bootstrap.context.annotation;
|
||||
package org.springframework.bootstrap.context.test;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.bootstrap.context.annotation.ConfigurationProperties;
|
||||
import org.springframework.bootstrap.context.annotation.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
Loading…
Reference in New Issue
Block a user