Talk about MappingsEndpoint of springboot2.

  springboot

Order

This paper mainly studies MappingsEndpoint of springboot2.

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 are used here to create mappingsEndpoint, and then different MappingDescriptionProvider are created according to whether they are servlets or reactive. Servlets create ServletSmappingDescriptionProviders. FiltersMappingDescriptionProvider, DispatcherServerLetsMappingDescriptionProvider, and reactive created 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());
    }
    //......
}

ContextMappings are created here based on descriptionProviders.

Servlet mode

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";
    }

}

Here, ServletRegistrations are obtained from servletContext, and then servletregisterrationmappingdescription is obtained.

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";
    }

}

Here, the FilterRegistrations are obtained from the servletContext, and then the filterRegistrationMappingDescription is obtained.

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();
    }
    //......
}

Here, the dispatcher servletmappingdescription is mainly obtained from delegatingghandlemappingdescription provider, requestmappingginfohandlermappingdescription provider, urlhandlermappingdescription provider.

Reactive approach

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();
    }
    //......
}

Unlike servlet obtaining dispatcher servletsmappingdescriptionprovider, reactive obtains dispatcher handlersmappingdescriptionprovider
The HandlerMappingDescriptionProvider is mainly obtained from RequestMappingInFoHandlerMappingDescriptionProvider, RouterFunctionMappingDescriptionProvider, UrlHandlerMappingDescriptionProvider.

Summary

MappingsEndpoint of springboot2 is obtained by provider according to servlet and reactive respectively. Servlet are mainly divided into ServletSmappingDescriptionProvider, FiltersSmappingDescriptionProvider, DispatchersServletSmappingDescriptionProvider, while reactive is mainly divided into DispatchersHandlerSmappingDescriptionProvider.

doc