Привод пружинной загрузки без пружинной загрузки
Я работал над приложением Spring/Spring MVC и собираюсь добавить показатели производительности. Я сталкивался с приводом Spring Boot, и это выглядит как отличное решение. Однако мое приложение не является приложением 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 {
}
Я даже зашел так далеко, что добавил @EnableConfigurationProperties для каждого класса конфигурации, как это было предложено в другом посте в Stackru. Однако это ничего не сделало. Конечные точки все еще не создаются и возвращают 404.
9 ответов
Вы можете использовать привод без пружинного чехла. Добавьте это в 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);
}
}
И тогда вы можете увидеть метрики в вашем приложении
Для начала давайте поясним, что вы не можете использовать Spring Boot Actuator без использования Spring Boot.
Я был неправ, что не смог этого сделать без Spring Boot. Посмотрите ответ @stefaan-neyts для примера того, как это сделать.
Я создал пример проекта, чтобы показать, как вы можете конвертировать базовое приложение SpringMVC, используя минимальное количество автоконфигурации Spring Boot.
Первоисточник: http://www.mkyong.com/spring-mvc/gradle-spring-mvc-web-project-example
Преобразованный источник: https://github.com/Pytry/minimal-boot-actuator
Я мог бы полностью удалить dispatcher-servlet.xml и файлы web.xml, но сохранил их, чтобы показать, как выполнить минимально возможное изменение и упростить преобразование более сложных проектов.
Вот список шагов, которые я предпринял для преобразования.
Процесс конверсии
- Добавьте файл конфигурации Java с аннотацией @SpringBootApplication
- Добавьте файл конфигурации приложения в виде bean-компонента к традиционной конфигурации xml (он был добавлен сразу после сканирования контекста).
Переместите преобразователи представлений в конфигурацию Java-приложения.
Или добавьте префикс и суффикс в application.properties. Затем вы можете внедрить их с помощью @Value в свое приложение или полностью удалить их и просто использовать предоставленный весенний загрузчик. Я пошел с первым.
Удален прослушиватель контекста по умолчанию из контекста Spring xml.
Это важно! Поскольку весенняя загрузка предоставит ее, вы получите исключение "Запуск прослушивателя ошибок", если вы этого не сделаете.
Добавьте плагин весенней загрузки в зависимости от сценария сборки (я использовал gradle)
Добавьте свойство mainClassName в файл сборки и задайте пустую строку (указывает на то, что не следует создавать исполняемый файл).
Изменить зависимости для пружинного привода привода
Хотя использование 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>
Поскольку у нас уже есть Spring Boot Actuator 2.x, рецепт включения привода в существующий проект 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)
Хотя ответ уже принят, я подумал об обновлении своего опыта. Я не хотел конвертировать мое приложение в весеннюю загрузку, используя @SpringBootApplication
, Обратитесь к другому вопросу, где я упомянул необходимый минимальный код.
Если ваша цель — создать конечную точку с метриками для Prometheus, также известной как OpenMetrics, вы можете использовать клиент Prometheus JVM , совместимый с инфраструктурой Spring.
Добавить зависимость:
<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-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
конечная точка.
Проходит время, у нас есть Spring 6, SpringBoot 3, JakartaEE в качестве основы, но люди все еще хотят добавить привод в устаревшие приложения Spring. Итак, небольшой апдейт: пружина + актуатор без пружины-пыльника. На самом деле мало что изменилось (а изменения уже были отмечены).
Зависимости
<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>
Вам нужно будет преобразовать ваше приложение в Spring Boot, если вы хотите использовать компоненты, подключаемые к нему. В документации по Spring Boot есть раздел "Преобразование существующего приложения в Spring Boot", который вы хотите просмотреть. Я сам этого не делал, но использую Spring Boot, и его настроить довольно просто, так что, надеюсь, вы сможете получить его отсюда.
Вы допустили ошибку, не добавив аннотацию @springboot в свой код. Когда вы добавляете @springboot, он автоматически будет считаться загрузочной программой компилятором и добавит для нее необходимый файл зависимостей и файл зависимостей вашего привода.