如何将 HandlerInterceptor 应用于 Spring Boot Actuator 端点?

How to apply HandlerInterceptor to Spring Boot Actuator endpoints?

我正在使用 Java 8Spring 1.2.3 构建应用程序 运行 在 Tomcat 7 容器内。

我确实使用非常简单的 HandlerInterceptor 拦截了对我的 Web 应用程序的每一次调用,它记录了创建响应所花费的总时间以及每个请求的 return 代码。

我通过简单地添加 spring-boot-starter-actuator 依赖项来激活执行器端点,并通过调用

添加拦截器
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private Application application;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(application.executeTimeInterceptor());
    }

}

显然,由 Spring Boot Actuator(/info/health 等)管理的所有端点都不会被拦截:我如何确保拦截器拦截对我的应用程序的所有调用,包括调用执行器提供的端点的调用?

在 tomcat 中,您还可以添加一个阀门来拦截对 Web 服务器的调用。阀门将拦截所有的端点,无论它们的拦截器堆栈如何。

这里有一个关于如何在 spring 引导中实现阀的示例:

@Configuration
public class TomcatConfiguration {

    private static final Logger LOG = LoggerFactory.getLogger(TomcatConfiguration.class);

    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        final TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addContextValves(new ValveBase() {
            @Override
            public void invoke(final Request request, final Response response) throws IOException, ServletException {
                final long start = System.currentTimeMillis();
                getNext().invoke(request, response);
                LOG.debug("Used time to invoke " + request.getRequestURI() + " : " + (System.currentTimeMillis() - start));
            }
        });
        return tomcat;
    }

}

在Spring Boot 1.x中,您可以使用EndpointHandlerMappingCustomizer来配置Actuator端点的拦截器。例如:

@Bean
public EndpointHandlerMappingCustomizer mappingCustomizer() {
    return new EndpointHandlerMappingCustomizer() {

        @Override
        public void customize(EndpointHandlerMapping mapping) {
            mapping.setInterceptors(new Object[] { application.executeTimeInterceptor() });
        }

    };
}