序
本文主要研究下springboot2的MappingsEndpoint
MappingsEndpointAutoConfiguration
spring-boot-actuator-autoconfigure-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration.java
@ManagementContextConfiguration
public class MappingsEndpointAutoConfiguration {
@Bean
@ConditionalOnEnabledEndpoint
public MappingsEndpoint mappingsEndpoint(ApplicationContext applicationContext,
ObjectProvider<Collection<MappingDescriptionProvider>> descriptionProviders) {
return new MappingsEndpoint(
descriptionProviders.getIfAvailable(Collections::emptyList),
applicationContext);
}
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
static class ServletWebConfiguration {
@Bean
ServletsMappingDescriptionProvider servletMappingDescriptionProvider() {
return new ServletsMappingDescriptionProvider();
}
@Bean
FiltersMappingDescriptionProvider filterMappingDescriptionProvider() {
return new FiltersMappingDescriptionProvider();
}
@Configuration
@ConditionalOnClass(DispatcherServlet.class)
@ConditionalOnBean(DispatcherServlet.class)
static class SpringMvcConfiguration {
@Bean
DispatcherServletsMappingDescriptionProvider dispatcherServletMappingDescriptionProvider() {
return new DispatcherServletsMappingDescriptionProvider();
}
}
}
@Configuration
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnClass(DispatcherHandler.class)
@ConditionalOnBean(DispatcherHandler.class)
static class ReactiveWebConfiguration {
@Bean
public DispatcherHandlersMappingDescriptionProvider dispatcherHandlerMappingDescriptionProvider(
ApplicationContext applicationContext) {
return new DispatcherHandlersMappingDescriptionProvider();
}
}
}
这里使用descriptionProviders创建mappingsEndpoint,然后根据是servlet或reactive的方式来创建不同的MappingDescriptionProvider,servlet创建的是ServletsMappingDescriptionProvider,FiltersMappingDescriptionProvider,DispatcherServletsMappingDescriptionProvider,reactive创建的是DispatcherHandlersMappingDescriptionProvider
MappingsEndpoint
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/MappingsEndpoint.java
@Endpoint(id = "mappings")
public class MappingsEndpoint {
private final Collection<MappingDescriptionProvider> descriptionProviders;
private final ApplicationContext context;
public MappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
ApplicationContext context) {
this.descriptionProviders = descriptionProviders;
this.context = context;
}
@ReadOperation
public ApplicationMappings mappings() {
ApplicationContext target = this.context;
Map<String, ContextMappings> contextMappings = new HashMap<>();
while (target != null) {
contextMappings.put(target.getId(), mappingsForContext(target));
target = target.getParent();
}
return new ApplicationMappings(contextMappings);
}
private ContextMappings mappingsForContext(ApplicationContext applicationContext) {
Map<String, Object> mappings = new HashMap<>();
this.descriptionProviders
.forEach((provider) -> mappings.put(provider.getMappingName(),
provider.describeMappings(applicationContext)));
return new ContextMappings(mappings, applicationContext.getParent() == null ? null
: applicationContext.getId());
}
//......
}
这里根据descriptionProviders创建ContextMappings
servlet方式
ServletsMappingDescriptionProvider
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/ServletsMappingDescriptionProvider.java
public class ServletsMappingDescriptionProvider implements MappingDescriptionProvider {
@Override
public List<ServletRegistrationMappingDescription> describeMappings(
ApplicationContext context) {
if (!(context instanceof WebApplicationContext)) {
return Collections.emptyList();
}
return ((WebApplicationContext) context).getServletContext()
.getServletRegistrations().values().stream()
.map(ServletRegistrationMappingDescription::new)
.collect(Collectors.toList());
}
@Override
public String getMappingName() {
return "servlets";
}
}
这里从servletContext中获取ServletRegistrations,再获取ServletRegistrationMappingDescription
FiltersMappingDescriptionProvider
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/FiltersMappingDescriptionProvider.java
public class FiltersMappingDescriptionProvider implements MappingDescriptionProvider {
@Override
public List<FilterRegistrationMappingDescription> describeMappings(
ApplicationContext context) {
if (!(context instanceof WebApplicationContext)) {
return Collections.emptyList();
}
return ((WebApplicationContext) context).getServletContext()
.getFilterRegistrations().values().stream()
.map(FilterRegistrationMappingDescription::new)
.collect(Collectors.toList());
}
@Override
public String getMappingName() {
return "servletFilters";
}
}
这里从servletContext中获取FilterRegistrations,再获取FilterRegistrationMappingDescription
DispatcherServletsMappingDescriptionProvider
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletsMappingDescriptionProvider.java
public class DispatcherServletsMappingDescriptionProvider
implements MappingDescriptionProvider {
private static final List<HandlerMappingDescriptionProvider<? extends HandlerMapping>> descriptionProviders;
static {
List<HandlerMappingDescriptionProvider<? extends HandlerMapping>> providers = new ArrayList<>();
providers.add(new RequestMappingInfoHandlerMappingDescriptionProvider());
providers.add(new UrlHandlerMappingDescriptionProvider());
if (ClassUtils.isPresent(
"org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping",
null)) {
providers.add(new DelegatingHandlerMappingDescriptionProvider(
new ArrayList<>(providers)));
}
descriptionProviders = Collections.unmodifiableList(providers);
}
@Override
public String getMappingName() {
return "dispatcherServlets";
}
@Override
public Map<String, List<DispatcherServletMappingDescription>> describeMappings(
ApplicationContext context) {
if (context instanceof WebApplicationContext) {
return describeMappings((WebApplicationContext) context);
}
return Collections.emptyMap();
}
private Map<String, List<DispatcherServletMappingDescription>> describeMappings(
WebApplicationContext context) {
Map<String, List<DispatcherServletMappingDescription>> mappings = new HashMap<>();
context.getBeansOfType(DispatcherServlet.class)
.forEach((name, dispatcherServlet) -> mappings.put(name,
describeMappings(new DispatcherServletHandlerMappings(name,
dispatcherServlet, context))));
return mappings;
}
private List<DispatcherServletMappingDescription> describeMappings(
DispatcherServletHandlerMappings mappings) {
return mappings.getHandlerMappings().stream().flatMap(this::describe)
.collect(Collectors.toList());
}
private <T extends HandlerMapping> Stream<DispatcherServletMappingDescription> describe(
T handlerMapping) {
return describe(handlerMapping, descriptionProviders).stream();
}
@SuppressWarnings("unchecked")
private static <T extends HandlerMapping> List<DispatcherServletMappingDescription> describe(
T handlerMapping,
List<HandlerMappingDescriptionProvider<?>> descriptionProviders) {
for (HandlerMappingDescriptionProvider<?> descriptionProvider : descriptionProviders) {
if (descriptionProvider.getMappingClass().isInstance(handlerMapping)) {
return ((HandlerMappingDescriptionProvider<T>) descriptionProvider)
.describe(handlerMapping);
}
}
return Collections.emptyList();
}
//......
}
这里主要从DelegatingHandlerMappingDescriptionProvider、RequestMappingInfoHandlerMappingDescriptionProvider、UrlHandlerMappingDescriptionProvider获取DispatcherServletMappingDescription
reactive方式
DispatcherHandlersMappingDescriptionProvider
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/reactive/DispatcherHandlersMappingDescriptionProvider.java
public class DispatcherHandlersMappingDescriptionProvider
implements MappingDescriptionProvider {
private static final List<HandlerMappingDescriptionProvider<? extends HandlerMapping>> descriptionProviders = Arrays
.asList(new RequestMappingInfoHandlerMappingDescriptionProvider(),
new UrlHandlerMappingDescriptionProvider(),
new RouterFunctionMappingDescriptionProvider());
@Override
public String getMappingName() {
return "dispatcherHandlers";
}
@Override
public Map<String, List<DispatcherHandlerMappingDescription>> describeMappings(
ApplicationContext context) {
Map<String, List<DispatcherHandlerMappingDescription>> mappings = new HashMap<>();
context.getBeansOfType(DispatcherHandler.class).forEach(
(name, handler) -> mappings.put(name, describeMappings(handler)));
return mappings;
}
private List<DispatcherHandlerMappingDescription> describeMappings(
DispatcherHandler dispatcherHandler) {
return dispatcherHandler.getHandlerMappings().stream().flatMap(this::describe)
.collect(Collectors.toList());
}
@SuppressWarnings("unchecked")
private <T extends HandlerMapping> Stream<DispatcherHandlerMappingDescription> describe(
T handlerMapping) {
for (HandlerMappingDescriptionProvider<?> descriptionProvider : descriptionProviders) {
if (descriptionProvider.getMappingClass().isInstance(handlerMapping)) {
return ((HandlerMappingDescriptionProvider<T>) descriptionProvider)
.describe(handlerMapping).stream();
}
}
return Stream.empty();
}
//......
}
与servlet获取DispatcherServletsMappingDescriptionProvider不同,reactive获取的是DispatcherHandlersMappingDescriptionProvider
主要从RequestMappingInfoHandlerMappingDescriptionProvider、RouterFunctionMappingDescriptionProvider、UrlHandlerMappingDescriptionProvider这三个来获取HandlerMappingDescriptionProvider
小结
springboot2的MappingsEndpoint通过provider根据servlet及reactive分别进行各自的mappings获取,servlet主要分为ServletsMappingDescriptionProvider、FiltersMappingDescriptionProvider、DispatcherServletsMappingDescriptionProvider,而reactive主要分为DispatcherHandlersMappingDescriptionProvider