本文主要研究下springboot2的MappingsEndpointhtml
spring-boot-actuator-autoconfigure-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/web/mappings/MappingsEndpointAutoConfiguration.javajava
@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
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/MappingsEndpoint.javareact
@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
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/ServletsMappingDescriptionProvider.javaweb
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
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/FiltersMappingDescriptionProvider.javaspring
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
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/servlet/DispatcherServletsMappingDescriptionProvider.javaspringboot
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
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/web/mappings/reactive/DispatcherHandlersMappingDescriptionProvider.javamvc
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主要分爲DispatcherHandlersMappingDescriptionProviderapp