Add server.tomcat.access_valve_enabled flag
Also introduced new strategy for customizing Tomcat Context (TomcatContextCustomizer) - any that are added to the factory will be applied before any other customizations in postProcessContext() [Fixes #54670052] [bs-275] Make Tomcat access valve logs more accessible
This commit is contained in:
parent
dc812ddf17
commit
d2419a36fd
|
@ -1,2 +1,4 @@
|
||||||
# Allow Thymeleaf templates to be reloaded at dev time
|
# Allow Thymeleaf templates to be reloaded at dev time
|
||||||
spring.template.cache: false
|
spring.template.cache: false
|
||||||
|
server.tomcat.access_log_enabled: true
|
||||||
|
server.tomcat.basedir: target/tomcat
|
|
@ -21,12 +21,14 @@ import java.net.InetAddress;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
import org.apache.catalina.valves.AccessLogValve;
|
import org.apache.catalina.valves.AccessLogValve;
|
||||||
import org.apache.catalina.valves.RemoteIpValve;
|
import org.apache.catalina.valves.RemoteIpValve;
|
||||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||||
|
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -107,12 +109,32 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||||
|
|
||||||
private String accessLogPattern;
|
private String accessLogPattern;
|
||||||
|
|
||||||
|
private boolean accessLogEnabled = false;
|
||||||
|
|
||||||
private String protocolHeader = "x-forwarded-proto";
|
private String protocolHeader = "x-forwarded-proto";
|
||||||
|
|
||||||
private String remoteIpHeader = "x-forwarded-for";
|
private String remoteIpHeader = "x-forwarded-for";
|
||||||
|
|
||||||
private File basedir;
|
private File basedir;
|
||||||
|
|
||||||
|
private int backgroundProcessorDelay = 30; // seconds
|
||||||
|
|
||||||
|
public boolean getAccessLogEnabled() {
|
||||||
|
return this.accessLogEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessLogEnabled(boolean accessLogEnabled) {
|
||||||
|
this.accessLogEnabled = accessLogEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBackgroundProcessorDelay() {
|
||||||
|
return this.backgroundProcessorDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBackgroundProcessorDelay(int backgroundProcessorDelay) {
|
||||||
|
this.backgroundProcessorDelay = backgroundProcessorDelay;
|
||||||
|
}
|
||||||
|
|
||||||
public File getBasedir() {
|
public File getBasedir() {
|
||||||
return this.basedir;
|
return this.basedir;
|
||||||
}
|
}
|
||||||
|
@ -150,6 +172,13 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||||
factory.setBaseDirectory(getBasedir());
|
factory.setBaseDirectory(getBasedir());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory.addContextCustomizers(new TomcatContextCustomizer() {
|
||||||
|
@Override
|
||||||
|
public void customize(Context context) {
|
||||||
|
context.setBackgroundProcessorDelay(Tomcat.this.backgroundProcessorDelay);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
String remoteIpHeader = getRemoteIpHeader();
|
String remoteIpHeader = getRemoteIpHeader();
|
||||||
String protocolHeader = getProtocolHeader();
|
String protocolHeader = getProtocolHeader();
|
||||||
if (StringUtils.hasText(remoteIpHeader)
|
if (StringUtils.hasText(remoteIpHeader)
|
||||||
|
@ -160,10 +189,15 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||||
factory.addContextValves(valve);
|
factory.addContextValves(valve);
|
||||||
}
|
}
|
||||||
|
|
||||||
String accessLogPattern = getAccessLogPattern();
|
if (this.accessLogEnabled) {
|
||||||
if (accessLogPattern != null) {
|
|
||||||
AccessLogValve valve = new AccessLogValve();
|
AccessLogValve valve = new AccessLogValve();
|
||||||
valve.setPattern(accessLogPattern);
|
String accessLogPattern = getAccessLogPattern();
|
||||||
|
if (accessLogPattern != null) {
|
||||||
|
valve.setPattern(accessLogPattern);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
valve.setPattern("common");
|
||||||
|
}
|
||||||
valve.setSuffix(".log");
|
valve.setSuffix(".log");
|
||||||
factory.addContextValves(valve);
|
factory.addContextValves(valve);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.boot.context.embedded.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Dave Syer
|
||||||
|
*/
|
||||||
|
public interface TomcatContextCustomizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context the context to customize
|
||||||
|
*/
|
||||||
|
void customize(Context context);
|
||||||
|
|
||||||
|
}
|
|
@ -72,6 +72,8 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||||
|
|
||||||
private List<LifecycleListener> contextLifecycleListeners = new ArrayList<LifecycleListener>();
|
private List<LifecycleListener> contextLifecycleListeners = new ArrayList<LifecycleListener>();
|
||||||
|
|
||||||
|
private List<TomcatContextCustomizer> tomcatContextCustomizers = new ArrayList<TomcatContextCustomizer>();
|
||||||
|
|
||||||
private ResourceLoader resourceLoader;
|
private ResourceLoader resourceLoader;
|
||||||
|
|
||||||
private String protocol = DEFAULT_PROTOCOL;
|
private String protocol = DEFAULT_PROTOCOL;
|
||||||
|
@ -221,6 +223,9 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||||
context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
|
context.addMimeMapping(mapping.getExtension(), mapping.getMimeType());
|
||||||
}
|
}
|
||||||
context.setSessionTimeout(getSessionTimeout());
|
context.setSessionTimeout(getSessionTimeout());
|
||||||
|
for (TomcatContextCustomizer customizer : this.tomcatContextCustomizers) {
|
||||||
|
customizer.customize(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -342,4 +347,37 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||||
this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners));
|
this.contextLifecycleListeners.addAll(Arrays.asList(contextLifecycleListeners));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set {@link TomcatContextCustomizer}s that should be applied to the Tomcat
|
||||||
|
* {@link Context} . Calling this method will replace any existing customizers.
|
||||||
|
* @param tomcatContextCustomizers the customizers to set
|
||||||
|
*/
|
||||||
|
public void setTomcatContextCustomizers(
|
||||||
|
Collection<? extends TomcatContextCustomizer> tomcatContextCustomizers) {
|
||||||
|
Assert.notNull(this.contextLifecycleListeners,
|
||||||
|
"TomcatContextCustomizers must not be null");
|
||||||
|
this.tomcatContextCustomizers = new ArrayList<TomcatContextCustomizer>(
|
||||||
|
tomcatContextCustomizers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable collection of the {@link TomcatContextCustomizer}s that will be
|
||||||
|
* applied to the Tomcat {@link Context} .
|
||||||
|
* @return the tomcatContextCustomizers the listeners that will be applied
|
||||||
|
*/
|
||||||
|
public Collection<TomcatContextCustomizer> getTomcatContextCustomizers() {
|
||||||
|
return this.tomcatContextCustomizers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add {@link TomcatContextCustomizer}s that should be added to the Tomcat
|
||||||
|
* {@link Context}.
|
||||||
|
* @param tomcatContextCustomizers the customizers to add
|
||||||
|
*/
|
||||||
|
public void addContextCustomizers(TomcatContextCustomizer... tomcatContextCustomizers) {
|
||||||
|
Assert.notNull(this.tomcatContextCustomizers,
|
||||||
|
"TomcatContextCustomizer must not be null");
|
||||||
|
this.tomcatContextCustomizers.addAll(Arrays.asList(tomcatContextCustomizers));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,6 @@ import org.apache.catalina.startup.Tomcat;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
|
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
|
||||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer;
|
|
||||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
@ -65,6 +63,22 @@ public class TomcatEmbeddedServletContainerFactoryTests extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void tomcatCustomizers() throws Exception {
|
||||||
|
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||||
|
TomcatContextCustomizer[] listeners = new TomcatContextCustomizer[4];
|
||||||
|
for (int i = 0; i < listeners.length; i++) {
|
||||||
|
listeners[i] = mock(TomcatContextCustomizer.class);
|
||||||
|
}
|
||||||
|
factory.setTomcatContextCustomizers(Arrays.asList(listeners[0], listeners[1]));
|
||||||
|
factory.addContextCustomizers(listeners[2], listeners[3]);
|
||||||
|
this.container = factory.getEmbeddedServletContainer();
|
||||||
|
InOrder ordered = inOrder((Object[]) listeners);
|
||||||
|
for (TomcatContextCustomizer listener : listeners) {
|
||||||
|
ordered.verify(listener).customize((Context) anyObject());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sessionTimeout() throws Exception {
|
public void sessionTimeout() throws Exception {
|
||||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||||
|
|
Loading…
Reference in New Issue