Allow servlet context parmeters to be configured via declaratively

Previously, configuration of a ServletContext init parameter required
the use of a ServletContextInitializer bean. This commmit adds
support for declarative configuration via the environment using
server.context_parameters.<name>=<value>.

Closes gh-1791
This commit is contained in:
Andy Wilkinson 2014-11-17 20:06:14 +00:00
parent e0a0af436f
commit 05cf686713
5 changed files with 107 additions and 2 deletions

View File

@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.web;
import java.io.File;
import java.net.InetAddress;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.validation.constraints.NotNull;
@ -33,6 +35,7 @@ import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletCont
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.InitParameterConfiguringServletContextInitializer;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
@ -69,6 +72,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
private final Tomcat tomcat = new Tomcat();
private final Map<String, String> contextParameters = new HashMap<String, String>();
public Tomcat getTomcat() {
return this.tomcat;
}
@ -145,6 +150,10 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
this.ssl = ssl;
}
public Map<String, String> getContextParameters() {
return this.contextParameters;
}
public void setLoader(String value) {
// no op to support Tomcat running as a traditional container (not embedded)
}
@ -170,6 +179,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
getTomcat()
.customizeTomcat((TomcatEmbeddedServletContainerFactory) container);
}
container.addInitializers(new InitParameterConfiguringServletContextInitializer(
getContextParameters()));
}
public String[] getPathsArray(Collection<String> paths) {

View File

@ -17,6 +17,7 @@
package org.springframework.boot.autoconfigure.web;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -30,6 +31,7 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomi
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ -112,6 +114,19 @@ public class EmbeddedServletContainerAutoConfigurationTests {
assertEquals(9000, getContainerFactory().getPort());
}
@Test
public void initParametersAreConfiguredOnTheServletContext() {
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"server.context_parameters.a:alpha", "server.context_parameters.b:bravo");
this.context.register(BaseConfiguration.class);
this.context.refresh();
ServletContext servletContext = this.context.getServletContext();
assertEquals("alpha", servletContext.getInitParameter("a"));
assertEquals("bravo", servletContext.getInitParameter("b"));
}
private void verifyContext() {
MockEmbeddedServletContainerFactory containerFactory = getContainerFactory();
Servlet servlet = this.context.getBean(

View File

@ -54,6 +54,7 @@ content into your application; rather pick only the properties that you need.
server.port=8080
server.address= # bind to a specific NIC
server.session-timeout= # session timeout in seconds
server.context-parameters.*= # Servlet context init parameters, e.g. server.context-parameters.a=alpha
server.context-path= # the context path, defaults to '/'
server.servlet-path= # the servlet path, defaults to '/'
server.ssl.client-auth= # want or need

View File

@ -0,0 +1,50 @@
/*
* Copyright 2012-2014 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.context.embedded;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
/**
* A {@code ServletContextInitializer} that configures init parameters on the
* {@code ServletContext}.
*
* @author Andy Wilkinson
* @since 1.2.0
* @see ServletContext#setInitParameter(String, String)
*/
public class InitParameterConfiguringServletContextInitializer implements
ServletContextInitializer {
private final Map<String, String> parameters;
public InitParameterConfiguringServletContextInitializer(
Map<String, String> parameters) {
this.parameters = parameters;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
for (Entry<String, String> entry : this.parameters.entrySet()) {
servletContext.setInitParameter(entry.getKey(), entry.getValue());
}
}
}

View File

@ -17,8 +17,11 @@
package org.springframework.boot.context.embedded;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.servlet.Filter;
@ -42,6 +45,7 @@ import static org.mockito.Mockito.spy;
* Mock {@link EmbeddedServletContainerFactory}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
public class MockEmbeddedServletContainerFactory extends
AbstractEmbeddedServletContainerFactory {
@ -51,7 +55,8 @@ public class MockEmbeddedServletContainerFactory extends
@Override
public EmbeddedServletContainer getEmbeddedServletContainer(
ServletContextInitializer... initializers) {
this.container = spy(new MockEmbeddedServletContainer(initializers, getPort()));
this.container = spy(new MockEmbeddedServletContainer(
mergeInitializers(initializers), getPort()));
return this.container;
}
@ -119,8 +124,30 @@ public class MockEmbeddedServletContainerFactory extends
return registeredFilter.getRegistration();
}
});
final Map<String, String> initParameters = new HashMap<String, String>();
given(this.servletContext.setInitParameter(anyString(), anyString()))
.will(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation)
throws Throwable {
initParameters.put(
invocation.getArgumentAt(0, String.class),
invocation.getArgumentAt(1, String.class));
return null;
}
});
given(this.servletContext.getInitParameterNames()).willReturn(
MockEmbeddedServletContainer.<String> emptyEnumeration());
Collections.enumeration(initParameters.keySet()));
given(this.servletContext.getInitParameter(anyString())).willAnswer(
new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation)
throws Throwable {
return initParameters.get(invocation.getArgumentAt(0,
String.class));
}
});
given(this.servletContext.getAttributeNames()).willReturn(
MockEmbeddedServletContainer.<String> emptyEnumeration());
given(this.servletContext.getNamedDispatcher("default")).willReturn(