Replace @FrameworkEndpoint with MvcEndpoint interface
This commit is contained in:
parent
87e00cfae9
commit
7f1264bb65
|
|
@ -17,8 +17,6 @@
|
|||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
|
@ -30,23 +28,20 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.GenericMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
|
|
@ -63,7 +58,6 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
|
@ -97,7 +91,8 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EndpointHandlerMapping endpointHandlerMapping() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(mvcEndpoints()
|
||||
.getEndpoints());
|
||||
mapping.setDisabled(ManagementServerPort.get(this.applicationContext) != ManagementServerPort.SAME);
|
||||
mapping.setPrefix(this.managementServerProperties.getContextPath());
|
||||
return mapping;
|
||||
|
|
@ -133,48 +128,28 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
|||
};
|
||||
}
|
||||
|
||||
@Component
|
||||
protected static class GenericEndpointPostProcessor implements
|
||||
BeanDefinitionRegistryPostProcessor {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MvcEndpoints mvcEndpoints() {
|
||||
return new MvcEndpoints();
|
||||
}
|
||||
|
||||
private BeanDefinitionRegistry registry;
|
||||
@Bean
|
||||
@ConditionalOnBean(EnvironmentEndpoint.class)
|
||||
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||
return new EnvironmentMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
private Map<Class<? extends Endpoint<?>>, Class<?>> endpointTypes = new HashMap<Class<? extends Endpoint<?>>, Class<?>>();
|
||||
|
||||
public GenericEndpointPostProcessor() {
|
||||
this.endpointTypes.put(EnvironmentEndpoint.class,
|
||||
EnvironmentMvcEndpoint.class);
|
||||
this.endpointTypes.put(MetricsEndpoint.class, MetricsMvcEndpoint.class);
|
||||
this.endpointTypes.put(ShutdownEndpoint.class, ShutdownMvcEndpoint.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
|
||||
throws BeansException {
|
||||
for (String name : beanFactory.getBeanNamesForType(Endpoint.class)) {
|
||||
Class<?> type = getTypeForEndpoint(beanFactory.getType(name));
|
||||
BeanDefinitionBuilder bean = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(type);
|
||||
bean.addConstructorArgReference(name);
|
||||
this.registry.registerBeanDefinition("mvc." + name,
|
||||
bean.getBeanDefinition());
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> getTypeForEndpoint(Class<?> endpoint) {
|
||||
Class<?> type = GenericMvcEndpoint.class;
|
||||
if (this.endpointTypes.containsKey(endpoint)) {
|
||||
type = this.endpointTypes.get(endpoint);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
|
||||
throws BeansException {
|
||||
this.registry = registry;
|
||||
}
|
||||
@Bean
|
||||
@ConditionalOnBean(MetricsEndpoint.class)
|
||||
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||
return new MetricsMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(ShutdownEndpoint.class)
|
||||
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
return new ShutdownMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
private void createChildManagementContext() {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
|
|
@ -24,13 +27,16 @@ import org.springframework.beans.factory.HierarchicalBeanFactory;
|
|||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.actuate.endpoint.ManagementErrorEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.ManagementErrorEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
|
|
@ -38,7 +44,6 @@ import org.springframework.boot.context.embedded.ErrorPage;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
import org.springframework.web.servlet.HandlerAdapter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
|
@ -99,16 +104,19 @@ public class EndpointWebMvcChildContextConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public HandlerAdapter handlerAdapter() {
|
||||
public HandlerAdapter handlerAdapter(HttpMessageConverters converters) {
|
||||
// TODO: maybe this needs more configuration for non-basic response use cases
|
||||
RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
|
||||
adapter.setMessageConverters(new RestTemplate().getMessageConverters());
|
||||
adapter.setMessageConverters(converters.getConverters());
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HandlerMapping handlerMapping() {
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
public HandlerMapping handlerMapping(MvcEndpoints endpoints,
|
||||
ListableBeanFactory beanFactory) {
|
||||
Set<MvcEndpoint> set = new HashSet<MvcEndpoint>(endpoints.getEndpoints());
|
||||
set.addAll(beanFactory.getBeansOfType(MvcEndpoint.class).values());
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(set);
|
||||
// In a child context we definitely want to see the parent endpoints
|
||||
mapping.setDetectHandlerMethodsInAncestorContexts(true);
|
||||
return mapping;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.springframework.boot.actuate.autoconfigure;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.servlet.Filter;
|
||||
|
|
@ -210,7 +211,7 @@ public class ManagementSecurityAutoConfiguration {
|
|||
return NO_PATHS;
|
||||
}
|
||||
|
||||
List<Endpoint<?>> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
Set<? extends Endpoint<?>> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
List<String> paths = new ArrayList<String>(endpoints.size());
|
||||
for (Endpoint<?> endpoint : endpoints) {
|
||||
if (endpoint.isSensitive() == secure) {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import java.util.Map;
|
|||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.endpoint.AutoConfigurationReportEndpoint.Report;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationReport;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationReport.ConditionAndOutcome;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationReport.ConditionAndOutcomes;
|
||||
|
|
@ -32,8 +31,6 @@ import org.springframework.util.ClassUtils;
|
|||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
|
|
@ -45,7 +42,6 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "endpoints.autoconfig", ignoreUnknownFields = false)
|
||||
@FrameworkEndpoint
|
||||
public class AutoConfigurationReportEndpoint extends AbstractEndpoint<Report> {
|
||||
|
||||
@Autowired
|
||||
|
|
@ -56,8 +52,6 @@ public class AutoConfigurationReportEndpoint extends AbstractEndpoint<Report> {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public Report invoke() {
|
||||
return new Report(this.autoConfigurationReport);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,17 +17,13 @@
|
|||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
|
|
@ -56,9 +52,9 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
|
|||
*
|
||||
*/
|
||||
public class EndpointHandlerMapping extends RequestMappingHandlerMapping implements
|
||||
InitializingBean, ApplicationContextAware {
|
||||
ApplicationContextAware {
|
||||
|
||||
private List<Endpoint<?>> endpoints;
|
||||
private Set<? extends MvcEndpoint> endpoints;
|
||||
|
||||
private String prefix = "";
|
||||
|
||||
|
|
@ -67,8 +63,10 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
/**
|
||||
* Create a new {@link EndpointHandlerMapping} instance. All {@link Endpoint}s will be
|
||||
* detected from the {@link ApplicationContext}.
|
||||
* @param endpoints
|
||||
*/
|
||||
public EndpointHandlerMapping() {
|
||||
public EndpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
|
||||
this.endpoints = new HashSet<MvcEndpoint>(endpoints);
|
||||
// By default the static resource handler mapping is LOWEST_PRECEDENCE - 1
|
||||
setOrder(LOWEST_PRECEDENCE - 2);
|
||||
}
|
||||
|
|
@ -76,28 +74,20 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
if (this.endpoints == null) {
|
||||
this.endpoints = findEndpointBeans();
|
||||
if (!this.disabled) {
|
||||
for (MvcEndpoint endpoint : this.endpoints) {
|
||||
detectHandlerMethods(endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private List<Endpoint<?>> findEndpointBeans() {
|
||||
return new ArrayList(BeanFactoryUtils.beansOfTypeIncludingAncestors(
|
||||
getApplicationContext(), Endpoint.class).values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects @FrameworkEndpoint annotations in handler beans.
|
||||
*
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#isHandler(java.lang.Class)
|
||||
* Since all handler beans are passed into the constructor there is no need to detect
|
||||
* anything here
|
||||
*/
|
||||
@Override
|
||||
protected boolean isHandler(Class<?> beanType) {
|
||||
if (this.disabled) {
|
||||
return false;
|
||||
}
|
||||
return AnnotationUtils.findAnnotation(beanType, FrameworkEndpoint.class) != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -169,7 +159,7 @@ public class EndpointHandlerMapping extends RequestMappingHandlerMapping impleme
|
|||
/**
|
||||
* Return the endpoints
|
||||
*/
|
||||
public List<Endpoint<?>> getEndpoints() {
|
||||
return Collections.unmodifiableList(this.endpoints);
|
||||
public Set<? extends Endpoint<?>> getEndpoints() {
|
||||
return this.endpoints;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ import org.springframework.core.env.Environment;
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class EnvironmentMvcEndpoint extends GenericMvcEndpoint implements
|
||||
EnvironmentAware {
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ public class EnvironmentMvcEndpoint extends GenericMvcEndpoint implements
|
|||
super(delegate);
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
String result = this.environment.getProperty(name);
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* 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.actuate.endpoint.mvc;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Component
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface FrameworkEndpoint {
|
||||
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class GenericMvcEndpoint implements MvcEndpoint {
|
||||
|
||||
private Endpoint<?> delegate;
|
||||
|
|
@ -44,4 +43,17 @@ public class GenericMvcEndpoint implements MvcEndpoint {
|
|||
return this.delegate.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.delegate.isSensitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends Endpoint<?>> type = (Class<? extends Endpoint<?>>) this.delegate
|
||||
.getClass();
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.web.ErrorController;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
|
@ -35,7 +33,6 @@ import org.springframework.web.context.request.RequestContextHolder;
|
|||
* @author Dave Syer
|
||||
*/
|
||||
@ConfigurationProperties(name = "error")
|
||||
@FrameworkEndpoint
|
||||
public class ManagementErrorEndpoint implements MvcEndpoint {
|
||||
|
||||
private final ErrorController controller;
|
||||
|
|
@ -57,4 +54,14 @@ public class ManagementErrorEndpoint implements MvcEndpoint {
|
|||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,13 +20,13 @@ import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class MetricsMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
private MetricsEndpoint delegate;
|
||||
|
|
@ -36,7 +36,7 @@ public class MetricsMvcEndpoint extends GenericMvcEndpoint {
|
|||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name:.*}")
|
||||
@RequestMapping(value = "/{name:.*}", method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public Object value(@PathVariable String name) {
|
||||
Object value = this.delegate.invoke().get(name);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,19 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
|
||||
/**
|
||||
* A strategy for the MVC layer on top of an {@link Endpoint}. Implementations are allowed
|
||||
* to use <code>@RequestMapping</code> and the full Spring MVC machinery, but should not
|
||||
* use <code>@Controller</code> or <code>@RequestMapping</code> at the type level (since
|
||||
* that would lead to a double mapping of paths, once by the regular MVC handler mappings
|
||||
* and once by the {@link EndpointHandlerMapping}).
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface MvcEndpoint {
|
||||
public interface MvcEndpoint extends Endpoint<Object> {
|
||||
|
||||
String getPath();
|
||||
Class<?> getEndpointType();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.actuate.endpoint.mvc;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* A registry for all {@link MvcEndpoint} beans, and a factory for a set of generic ones
|
||||
* wrapping existing {@link Endpoint} instances that are not already exposed as MVC
|
||||
* endpoints.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@Component
|
||||
public class MvcEndpoints implements ApplicationContextAware, InitializingBean {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private Set<MvcEndpoint> endpoints = new HashSet<MvcEndpoint>();
|
||||
|
||||
private Set<Class<?>> customTypes;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Collection<MvcEndpoint> existing = this.applicationContext.getBeansOfType(
|
||||
MvcEndpoint.class).values();
|
||||
this.endpoints.addAll(existing);
|
||||
this.customTypes = findEndpointClasses(existing);
|
||||
@SuppressWarnings("rawtypes")
|
||||
Collection<Endpoint> delegates = this.applicationContext.getBeansOfType(
|
||||
Endpoint.class).values();
|
||||
for (Endpoint<?> endpoint : delegates) {
|
||||
if (isGenericEndpoint(endpoint.getClass())) {
|
||||
this.endpoints.add(new GenericMvcEndpoint(endpoint));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Class<?>> findEndpointClasses(Collection<MvcEndpoint> existing) {
|
||||
Set<Class<?>> types = new HashSet<Class<?>>();
|
||||
for (MvcEndpoint endpoint : existing) {
|
||||
Class<?> type = endpoint.getEndpointType();
|
||||
if (type != null) {
|
||||
types.add(type);
|
||||
}
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
public Set<? extends MvcEndpoint> getEndpoints() {
|
||||
return this.endpoints;
|
||||
}
|
||||
|
||||
private boolean isGenericEndpoint(Class<?> type) {
|
||||
return !this.customTypes.contains(type)
|
||||
&& !MvcEndpoint.class.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,7 +24,6 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@FrameworkEndpoint
|
||||
public class ShutdownMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public ShutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import java.nio.charset.Charset;
|
|||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.TestUtils;
|
||||
import org.springframework.boot.actuate.endpoint.AbstractEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.FrameworkEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||
import org.springframework.boot.actuate.properties.ManagementServerProperties;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
|
|
@ -240,20 +240,29 @@ public class EndpointWebMvcAutoConfigurationTests {
|
|||
|
||||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
public static class TestEndpoint extends AbstractEndpoint<String> {
|
||||
public static class TestEndpoint implements MvcEndpoint {
|
||||
|
||||
public TestEndpoint() {
|
||||
super("/endpoint", false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
@ResponseBody
|
||||
public String invoke() {
|
||||
return "endpointoutput";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPath() {
|
||||
return "/endpoint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getEndpointType() {
|
||||
return Endpoint.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
|
@ -44,14 +45,10 @@ import static org.junit.Assert.assertThat;
|
|||
public class EndpointHandlerMappingTests {
|
||||
|
||||
private StaticApplicationContext context = new StaticApplicationContext();
|
||||
private EndpointHandlerMapping mapping = new EndpointHandlerMapping();
|
||||
private Method method;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton("mapping",
|
||||
this.mapping);
|
||||
this.mapping.setApplicationContext(this.context);
|
||||
this.method = ReflectionUtils.findMethod(TestMvcEndpoint.class, "invoke");
|
||||
}
|
||||
|
||||
|
|
@ -59,18 +56,17 @@ public class EndpointHandlerMappingTests {
|
|||
public void withoutPrefix() throws Exception {
|
||||
TestMvcEndpoint endpointA = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
TestMvcEndpoint endpointB = new TestMvcEndpoint(new TestEndpoint("/b"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointA.getPath(), endpointA);
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointB.getPath(), endpointB);
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a"))
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(Arrays.asList(
|
||||
endpointA, endpointB));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a"))
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointA, this.method)));
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/b"))
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/b"))
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointB, this.method)));
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/c")),
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/c")),
|
||||
nullValue());
|
||||
}
|
||||
|
||||
|
|
@ -78,59 +74,62 @@ public class EndpointHandlerMappingTests {
|
|||
public void withPrefix() throws Exception {
|
||||
TestMvcEndpoint endpointA = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
TestMvcEndpoint endpointB = new TestMvcEndpoint(new TestEndpoint("/b"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointA.getPath(), endpointA);
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpointB.getPath(), endpointB);
|
||||
this.mapping.setPrefix("/a");
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a/a"))
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(Arrays.asList(
|
||||
endpointA, endpointB));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.setPrefix("/a");
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a/a"))
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointA, this.method)));
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a/b"))
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a/b"))
|
||||
.getHandler(),
|
||||
equalTo((Object) new HandlerMethod(endpointB, this.method)));
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
nullValue());
|
||||
}
|
||||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyGetHttpMethodForNonActionEndpoints() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertNotNull(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
assertNull(this.mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
assertNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postHttpMethodForActionEndpoints() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertNotNull(this.mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
}
|
||||
|
||||
@Test(expected = HttpRequestMethodNotSupportedException.class)
|
||||
public void onlyPostHttpMethodForActionEndpoints() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertNotNull(this.mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
assertNull(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
TestActionEndpoint endpoint = new TestActionEndpoint(new TestEndpoint("/a"));
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertNotNull(mapping.getHandler(new MockHttpServletRequest("POST", "/a")));
|
||||
assertNull(mapping.getHandler(new MockHttpServletRequest("GET", "/a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabled() throws Exception {
|
||||
TestMvcEndpoint endpoint = new TestMvcEndpoint(new TestEndpoint("/a"));
|
||||
this.context.getDefaultListableBeanFactory().registerSingleton(
|
||||
endpoint.getPath(), endpoint);
|
||||
this.mapping.setDisabled(true);
|
||||
this.mapping.afterPropertiesSet();
|
||||
assertThat(this.mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
EndpointHandlerMapping mapping = new EndpointHandlerMapping(
|
||||
Arrays.asList(endpoint));
|
||||
mapping.setDisabled(true);
|
||||
mapping.setApplicationContext(this.context);
|
||||
mapping.afterPropertiesSet();
|
||||
assertThat(mapping.getHandler(new MockHttpServletRequest("GET", "/a")),
|
||||
nullValue());
|
||||
}
|
||||
|
||||
|
|
@ -141,14 +140,12 @@ public class EndpointHandlerMappingTests {
|
|||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public Object invoke() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
private static class TestMvcEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public TestMvcEndpoint(TestEndpoint delegate) {
|
||||
|
|
@ -157,8 +154,7 @@ public class EndpointHandlerMappingTests {
|
|||
|
||||
}
|
||||
|
||||
@FrameworkEndpoint
|
||||
private static class TestActionEndpoint extends TestMvcEndpoint {
|
||||
private static class TestActionEndpoint extends GenericMvcEndpoint {
|
||||
|
||||
public TestActionEndpoint(TestEndpoint delegate) {
|
||||
super(delegate);
|
||||
|
|
@ -169,6 +165,7 @@ public class EndpointHandlerMappingTests {
|
|||
public Object invoke() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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.actuate.endpoint.mvc;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.TestUtils;
|
||||
import org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.mvc.EnvironmentMvcEndpointTests.TestConfiguration;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { TestConfiguration.class })
|
||||
@WebAppConfiguration
|
||||
public class EnvironmentMvcEndpointTests {
|
||||
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
private MockMvc mvc;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
TestUtils.addEnviroment((ConfigurableApplicationContext) this.context, "foo:bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void home() throws Exception {
|
||||
this.mvc.perform(get("/env")).andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString("systemProperties")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sub() throws Exception {
|
||||
this.mvc.perform(get("/env/foo")).andExpect(status().isOk())
|
||||
.andExpect(content().string(equalToIgnoringCase("bar")));
|
||||
}
|
||||
|
||||
@Import(EndpointWebMvcAutoConfiguration.class)
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
public static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
public EnvironmentEndpoint endpoint() {
|
||||
return new EnvironmentEndpoint();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EnvironmentMvcEndpoint mvcEndpoint() {
|
||||
return new EnvironmentMvcEndpoint(endpoint());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue