mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Reinstate support for relaxed binding for endpoint enablement
This commit improves upon the changes made in a8bf9d3
by adding
support for relaxed binding of the endpoints.enabled and
endpoints.<name>.enabled properties. This is achieved by replacing
use of @ConditionalOnExpression (which does not support relaxed
binding) with a custom condition implementation that uses
RelaxedPropertyResolver.
Closes gh-2767
This commit is contained in:
parent
d8f45ab6ca
commit
83f842a226
@ -17,6 +17,10 @@
|
|||||||
package org.springframework.boot.actuate.autoconfigure;
|
package org.springframework.boot.actuate.autoconfigure;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
@ -49,15 +53,17 @@ import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
|
|||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||||
|
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
@ -66,10 +72,14 @@ import org.springframework.context.ApplicationContextAware;
|
|||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.event.ContextClosedEvent;
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
import org.springframework.web.servlet.DispatcherServlet;
|
import org.springframework.web.servlet.DispatcherServlet;
|
||||||
@ -156,14 +166,14 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnBean(EnvironmentEndpoint.class)
|
@ConditionalOnBean(EnvironmentEndpoint.class)
|
||||||
@ConditionalOnExpression("${endpoints.env.enabled:${endpoints.enabled:true}}")
|
@ConditionalOnEnabledEndpoint("env")
|
||||||
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||||
return new EnvironmentMvcEndpoint(delegate);
|
return new EnvironmentMvcEndpoint(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnBean(HealthEndpoint.class)
|
@ConditionalOnBean(HealthEndpoint.class)
|
||||||
@ConditionalOnExpression("${endpoints.health.enabled:${endpoints.enabled:true}}")
|
@ConditionalOnEnabledEndpoint("health")
|
||||||
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
|
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
|
||||||
Security security = this.managementServerProperties.getSecurity();
|
Security security = this.managementServerProperties.getSecurity();
|
||||||
boolean secure = (security == null || security.isEnabled());
|
boolean secure = (security == null || security.isEnabled());
|
||||||
@ -177,14 +187,14 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnBean(MetricsEndpoint.class)
|
@ConditionalOnBean(MetricsEndpoint.class)
|
||||||
@ConditionalOnExpression("${endpoints.metrics.enabled:${endpoints.enabled:true}}")
|
@ConditionalOnEnabledEndpoint("metrics")
|
||||||
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
|
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||||
return new MetricsMvcEndpoint(delegate);
|
return new MetricsMvcEndpoint(delegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnBean(ShutdownEndpoint.class)
|
@ConditionalOnBean(ShutdownEndpoint.class)
|
||||||
@ConditionalOnExpression("${endpoints.shutdown.enabled:false}")
|
@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)
|
||||||
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||||
return new ShutdownMvcEndpoint(delegate);
|
return new ShutdownMvcEndpoint(delegate);
|
||||||
}
|
}
|
||||||
@ -330,4 +340,77 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link Conditional} that checks whether or not an endpoint is enabled. Matches if
|
||||||
|
* the value of the {@code endpoints.<name>.enabled} property is {@code true}. Does
|
||||||
|
* not match if the property's value or {@code enabledByDefault} is {@code false}.
|
||||||
|
* Otherwise, matches if the value of the {@code endpoints.enabled} property is
|
||||||
|
* {@code true} or if the property is not configured.
|
||||||
|
*
|
||||||
|
* @since 1.2.4
|
||||||
|
*/
|
||||||
|
@Conditional(OnEnabledEndpointCondition.class)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public static @interface ConditionalOnEnabledEndpoint {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the endpoint.
|
||||||
|
* @return The name of the endpoint
|
||||||
|
*/
|
||||||
|
public String value();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the endpoint is enabled by default.
|
||||||
|
* @return {@code true} if the endpoint is enabled by default, otherwise
|
||||||
|
* {@code false}
|
||||||
|
*/
|
||||||
|
public boolean enabledByDefault() default true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OnEnabledEndpointCondition extends SpringBootCondition {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||||
|
AnnotatedTypeMetadata metadata) {
|
||||||
|
AnnotationAttributes annotationAttributes = AnnotationAttributes
|
||||||
|
.fromMap(metadata.getAnnotationAttributes(ConditionalOnEnabledEndpoint.class
|
||||||
|
.getName()));
|
||||||
|
String endpointName = annotationAttributes.getString("value");
|
||||||
|
boolean enabledByDefault = annotationAttributes
|
||||||
|
.getBoolean("enabledByDefault");
|
||||||
|
ConditionOutcome specificEndpointOutcome = determineSpecificEndpointOutcome(
|
||||||
|
endpointName, enabledByDefault, context);
|
||||||
|
if (specificEndpointOutcome != null) {
|
||||||
|
return specificEndpointOutcome;
|
||||||
|
}
|
||||||
|
return determineAllEndpointsOutcome(context);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConditionOutcome determineSpecificEndpointOutcome(String endpointName,
|
||||||
|
boolean enabledByDefault, ConditionContext context) {
|
||||||
|
RelaxedPropertyResolver endpointPropertyResolver = new RelaxedPropertyResolver(
|
||||||
|
context.getEnvironment(), "endpoints." + endpointName + ".");
|
||||||
|
if (endpointPropertyResolver.containsProperty("enabled") || !enabledByDefault) {
|
||||||
|
boolean match = endpointPropertyResolver.getProperty("enabled",
|
||||||
|
Boolean.class, enabledByDefault);
|
||||||
|
return new ConditionOutcome(match, "The " + endpointName + " is "
|
||||||
|
+ (match ? "enabled" : "disabled"));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ConditionOutcome determineAllEndpointsOutcome(ConditionContext context) {
|
||||||
|
RelaxedPropertyResolver allEndpointsPropertyResolver = new RelaxedPropertyResolver(
|
||||||
|
context.getEnvironment(), "endpoints.");
|
||||||
|
boolean match = Boolean.valueOf(allEndpointsPropertyResolver.getProperty(
|
||||||
|
"enabled", "true"));
|
||||||
|
return new ConditionOutcome(match, "All endpoints are "
|
||||||
|
+ (match ? "enabled" : "disabled") + " by default");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||||||
this.applicationContext.register(RootConfig.class, BaseConfiguration.class,
|
this.applicationContext.register(RootConfig.class, BaseConfiguration.class,
|
||||||
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
||||||
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
||||||
"endpoints.enabled:false");
|
"ENDPOINTS_ENABLED:false");
|
||||||
this.applicationContext.refresh();
|
this.applicationContext.refresh();
|
||||||
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class).size(),
|
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class).size(),
|
||||||
is(equalTo(0)));
|
is(equalTo(0)));
|
||||||
@ -342,7 +342,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||||||
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
||||||
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
||||||
"endpoints.enabled:false",
|
"endpoints.enabled:false",
|
||||||
String.format("endpoints.%s.enabled:true", name));
|
String.format("endpoints_%s_enabled:true", name));
|
||||||
this.applicationContext.refresh();
|
this.applicationContext.refresh();
|
||||||
assertThat(this.applicationContext.getBeansOfType(type).size(), is(equalTo(1)));
|
assertThat(this.applicationContext.getBeansOfType(type).size(), is(equalTo(1)));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user