不使用Spring Boot,使用Spring Boot Actuator

86

我正在开发一个Spring/Spring MVC应用程序,想要添加性能指标。我发现了Spring Boot Actuator,它似乎是一个很好的解决方案。但是我的应用程序不是Spring Boot应用程序,而是运行在传统容器Tomcat 8中。

我添加了以下依赖项:

// Spring Actuator
compile "org.springframework.boot:spring-boot-starter-actuator:1.2.3.RELEASE"

我创建了以下的配置类。

@EnableConfigurationProperties
@Configuration
@EnableAutoConfiguration
@Profile(value = {"dev", "test"})
@Import(EndpointAutoConfiguration.class)
public class SpringActuatorConfig {

}

我甚至按照StackOverflow上的另一个帖子建议,在每个配置类上添加@EnableConfigurationProperties,但没有起到任何作用。端点仍未被创建并返回404。


6
您可能已经知道了,但是您也可以使用Spring Boot为打包为war的应用程序;Spring Boot不要求您使用嵌入式Tomcat。 - gyoder
1
我其实并不太熟悉Spring Boot。Spring Boot与传统的Spring应用程序有何不同?据我所知,它只是一个具有特定Spring中心方法的起始模板。 - greyfox
3
它的不同之处在于,只要您对它自动配置的默认设置满意,它就会消除大量配置的需求。 - Kevin M
你能否发布你的构建文件? - Pytry
相关问题:https://dev59.com/4F8d5IYBdhLWcg3wXRIX - Adam Michalik
8个回答

37

首先需要澄清的是,您不能在不使用Spring Boot的情况下使用Spring Boot Actuator。

我之前关于没有使用Spring Boot就无法实现的想法是错误的。请查看@stefaan-neyts的答案,了解如何实现。

我创建了一个示例项目,展示了如何使用最少量的Spring Boot自动配置来转换基本的SpringMVC应用程序。

原始来源:http://www.mkyong.com/spring-mvc/gradle-spring-mvc-web-project-example

转换后的来源:https://github.com/Pytry/minimal-boot-actuator

我本可以完全删除dispatcher-servlet.xml和web.xml文件,但我保留它们以展示如何尽可能地进行最小更改,并简化转换更复杂的项目。

以下是我进行转换的步骤列表:

转换过程

  • 添加一个带有@SpringBootApplication注解的Java配置文件
  • 将应用程序配置文件作为bean添加到传统的xml配置中(在上下文扫描后立即添加)。
  • 将视图解析器移动到应用程序的Java配置文件中。

    或者,将前缀和后缀添加到application.properties中。 然后,您可以在应用程序中使用@Value注入它们,或者完全删除它并仅使用提供的Spring Boot视图解析器。 我选择了前者。

  • 从spring上下文xml中删除默认上下文侦听器。

    这很重要! 由于spring boot会提供一个默认的上下文侦听器,如果没有删除默认的上下文侦听器,则会出现"错误监听器启动"异常。

  • 将spring boot插件添加到构建脚本依赖项中(我使用的是gradle)

  • 向构建文件添加mainClassName属性,并将其设置为空字符串(表示不创建可执行文件)。

  • 修改spring boot actuator的依赖关系


2
非常有趣的讨论,但这样做是将经典的Spring MVC应用程序移植到使用WAR作为打包方式的Spring Boot应用程序。 - Valerio Vaudi
1
@ValerioVaudi 没错。关键是没有 Spring Boot,就无法使用 Spring Boot Actuator。 - Pytry
好的,很抱歉我没有看到你的第一个断言:“首先让我们澄清一下,如果不使用Spring Boot,就不能使用Spring Boot Actuator”。 - Valerio Vaudi
@ValerioVaudi 在你评论之后我添加了那个。你让我意识到我的回答没有表述清楚。 - Pytry
1
你可以在非 Spring Boot 应用程序中使用 Spring Boot Actuator。 - vsingh
@vsingh 我相信你是正确的,虽然我还没有做过...但我可能会在未来更新这个或者添加一个如何实现它的例子。如果你已经有了一个例子,让我们一起编辑答案并将其添加进去。 - Pytry

37

您可以在没有Spring Boot的情况下使用actuator。 将以下内容添加到pom.xml文件中:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>

接着在你的配置类中

@Configuration
@EnableWebMvc
@Import({
        EndpointAutoConfiguration.class , PublicMetricsAutoConfiguration.class , HealthIndicatorAutoConfiguration.class
})
public class MyActuatorConfig {

    @Bean
    @Autowired
    public EndpointHandlerMapping endpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
        return new EndpointHandlerMapping(endpoints);
    }

    @Bean
    @Autowired
    public EndpointMvcAdapter metricsEndPoint(MetricsEndpoint delegate) {
        return new EndpointMvcAdapter(delegate);
    }
}

接着您可以在应用程序中查看指标

http://localhost:8085/metrics

Actuator端点


1
这个版本的actuator 1.3.5.RELEASE启用了哪些其他端点? - Nikhil
@vsingh 当我这样做时,我会得到以下错误:Error creating bean with name 'org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration$InfoPropertiesConfiguration': Unsatisfied dependency expressed through field 'environment'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.env.ConfigurableEnvironment' available: expected at least 1 bean which qualifies as autowire candidate. 我应该在哪里配置这个bean呢? - JensW
你的应用程序是否可以在pom.xml中不添加上述内容的情况下启动?我似乎没有遇到过这个错误。ConfigurableEnvironment不是actuator包的一部分。 - vsingh
这对我不起作用。而且在上面的依赖项中找不到@EnableWebMvc。 - Pubudu Sitinamaluwa
3
你好@vsingh,我已按照上述说明添加了配置,但是当我访问http://localhost:port/metrics时,它返回404。我们需要在application.properties或yml文件中添加其他属性吗? - Romil Patel

18

虽然没有使用Spring Boot的Spring Boot功能不是一个好主意,但是这是可能的!

例如,以下Java配置使得Spring Boot Actuator指标在不使用Spring Boot的情况下可用:

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.PublicMetricsAutoConfiguration;
import org.springframework.boot.actuate.endpoint.MetricsEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
import org.springframework.boot.actuate.endpoint.mvc.EndpointMvcAdapter;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import({ EndpointAutoConfiguration.class, PublicMetricsAutoConfiguration.class })
public class SpringBootActuatorConfig {

    @Bean
    @Autowired
    public EndpointHandlerMapping endpointHandlerMapping(Collection<? extends MvcEndpoint> endpoints) {
        return new EndpointHandlerMapping(endpoints);
    }

    @Bean
    @Autowired
    public EndpointMvcAdapter metricsEndPoint(MetricsEndpoint delegate) {
        return new EndpointMvcAdapter(delegate);
    }
}

这是Maven的依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-actuator</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>

感谢@Stefaan提供的这个好建议,我需要添加到我的Maven依赖项中的唯一一件事是Bean Validation Provider依赖项,例如Hibernate Validator(<groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId>)。 - ngeek
不需要使用 @Autowired,在这种情况下 application.properties 中的 management.context-path=/manage 无效,你应该明确地设置 endpointHandlerMapping 的前缀。 - zhuguowei
你知道我如何在Spring Boot Actuator 2.7版本中实现它吗?@Stefaan Neyts - Pep

8

我们已经有了Spring Boot Actuator 2.x,将actuator添加到现有的Spring MVC项目的步骤可以如下:

@Configuration
@Import({
        EndpointAutoConfiguration.class,
        HealthIndicatorAutoConfiguration.class,

        InfoEndpointAutoConfiguration.class,
        HealthEndpointAutoConfiguration.class,

        WebEndpointAutoConfiguration.class,
        ServletManagementContextAutoConfiguration.class,
        ManagementContextAutoConfiguration.class,
})
@EnableConfigurationProperties(CorsEndpointProperties.class)
class ActuatorConfiguration {

    @Bean //taken from WebMvcEndpointManagementContextConfiguration.class
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
                                                                         ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
                                                                         EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
                                                                         WebEndpointProperties webEndpointProperties) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
        return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes,
                corsProperties.toCorsConfiguration(),
                new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()));
    }

    @Bean
    DispatcherServletPath dispatcherServletPath() {
        return () -> "/";
    }

}

我确实包含了

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator-autoconfigure</artifactId>
        <version>2.1.18.RELEASE</version>
    </dependency>

为了与我一直使用的基线Spring版本(5.1.19.RELEASE)兼容


1
无法找到HealthIndicatorAutoConfiguration - Poli
1
如果您使用的是2.7及以上版本,请改用> HealthContributorAutoConfiguration.class。 - Andres
较新的Spring Boot版本在类名和WebMvcEndpointHandlerMapping构造函数方面有一些更改。此外,需要添加依赖项“org.springframework.boot:spring-boot-actuator-autoconfigure”。 - Olavi Vaino

7

虽然已经有答案被接受了,但我想更新我的经验。我不想使用@SpringBootApplication将我的应用程序转换为spring boot。请参考另一个问题,在那里我提到了所需的最少代码。


我为这种方式添加了额外的解释 https://dev59.com/H1wX5IYBdhLWcg3wyCDT#41488749 - Dmytro Boichenko

1
如果您的目标是创建一个带有Prometheus或OpenMetrics指标的端点,您可以使用与Spring框架兼容的Prometheus JVM客户端
添加依赖项:
    <dependency>
      <groupId>io.prometheus</groupId>
      <artifactId>simpleclient_servlet</artifactId>
      <version>0.16.0</version>
    </dependency>

为了收集请求的指标,请将以下代码作为第一个过滤器添加到 web-app/WEB-INF/web.xml 文件中:

  <filter>
    <filter-name>prometheusFilter</filter-name>
    <filter-class>io.prometheus.client.filter.MetricsFilter</filter-class>
    <init-param>
      <param-name>metric-name</param-name>
      <param-value>webapp_metrics_filter</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>prometheusFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

为了将指标作为HTTP端点公开,添加Servlet:

  <servlet>
    <servlet-name>prometheus</servlet-name>
    <servlet-class>io.prometheus.client.exporter.MetricsServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>prometheus</servlet-name>
    <url-pattern>/metrics</url-pattern>
  </servlet-mapping>

之后您可以在/metrics端点上查看指标。


0
时间飞逝,我们已经有了Spring 6、SpringBoot 3、JakartaEE作为基线,但人们仍然希望将actuator添加到传统的spring应用程序中。因此,一个小更新:spring + actuator而不是spring-boot。实际上,并没有太多变化(这些变化已经被指出)。
依赖项:
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>6.0.3</version>
    </dependency>
    <dependency>
       <groupId>jakarta.servlet</groupId>
       <artifactId>jakarta.servlet-api</artifactId>
       <version>6.0.0</version>
       <scope>provided</scope>
    </dependency>
    
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-actuator-autoconfigure</artifactId>
       <version>3.0.1</version>
    </dependency>

执行器配置
@Configuration
@ImportAutoConfiguration({
    EndpointAutoConfiguration.class,
    WebEndpointAutoConfiguration.class,
    ServletManagementContextAutoConfiguration.class,
    ManagementContextAutoConfiguration.class,

    HealthContributorAutoConfiguration.class,

    InfoEndpointAutoConfiguration.class,
    HealthEndpointAutoConfiguration.class,

    HeapDumpWebEndpointAutoConfiguration.class,
    ThreadDumpEndpointAutoConfiguration.class,
    LoggersEndpointAutoConfiguration.class,
    PrometheusMetricsExportAutoConfiguration.class,
})
@EnableConfigurationProperties(CorsEndpointProperties.class)
class ActuatorConfiguration {

    @Bean //taken from WebMvcEndpointManagementContextConfiguration.class
    public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier,
        ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier,
        EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties,
        WebEndpointProperties webEndpointProperties) {
        List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
        Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
        allEndpoints.addAll(webEndpoints);
        allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
        allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
        EndpointMapping endpointMapping = new EndpointMapping(webEndpointProperties.getBasePath());
        return new WebMvcEndpointHandlerMapping(endpointMapping,
            webEndpoints,
            endpointMediaTypes,
            corsProperties.toCorsConfiguration(),
            new EndpointLinksResolver(allEndpoints, webEndpointProperties.getBasePath()),
            true);
    }

    @Bean
    DispatcherServletPath dispatcherServletPath() {
        return () -> WebInitializer.APPLICATION_ROOT;
    }

}

这个例子可以直接从Maven Jetty插件运行(mvn jetty:run-war)。

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>11.0.13</version>
            </plugin>

The final result


-10

你在代码中没有引入 @springboot 注解,这是一个错误。当你添加了 @springboot 注解后,编译器会自动将其视为引导程序,并添加所需的依赖文件和 actuator 依赖文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接