如何使`@Endpoint(id = "health")` 在 Spring Boot 2.0 中工作?
Posted
技术标签:
【中文标题】如何使`@Endpoint(id = "health")` 在 Spring Boot 2.0 中工作?【英文标题】:How to make the `@Endpoint(id = "health")` working in Spring Boot 2.0? 【发布时间】:2018-03-29 13:03:13 【问题描述】:我已经尝试过在 Spring Boot 2.0.0.M5 中自定义 health Actuator 的新方法,如下所述:https://spring.io/blog/2017/08/22/introducing-actuator-endpoints-in-spring-boot-2-0:
@Endpoint(id = "health")
public class HealthEndpoint
@ReadOperation
public Health health()
return new Health.Builder()
.up()
.withDetail("MyStatus", "is happy")
.build();
但是,当我对localhost:port/application/health
运行 HTTP GET 时,我仍然会得到标准的默认健康信息。我的代码完全被忽略了。
当我通过HealthIndicator
的实现使用自定义健康信息的“传统方式”时,它按预期工作,健康信息用给定的细节装饰:
@Component
public class MyHealthIndicator implements HealthIndicator
@Override
public Health health()
return new Health.Builder()
.up()
.withDetail("MyStatus 1.1", "is happy")
.withDetail("MyStatus 1.2", "is also happy")
.build();
问题:我还应该配置和/或实施什么才能使@Endpoint(id = "health")
解决方案工作?
我的意图不是创建自定义执行器myhealth
,而是自定义现有的health
执行器。根据文档,我希望达到与实施 HealthIndicator 相同的结果。我的假设错了吗?
Maven 配置pom.xml
包含:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M5</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
Spring Boot 配置application.properties
包含:
endpoints.health.enabled=true
endpoints.autoconfig.enabled=true
endpoints.autoconfig.web.enabled=true
【问题讨论】:
您是否将HealthEndpoint
配置为bean?为此,您通常会为其声明一个 @Bean
方法,或者,如果您使用组件扫描,请使用 @Component
注释它
@AndyWilkinson 好吧,我希望 @Endpoint
-annotated 类在 Spring Boot 中被自动扫描。但是,现在我尝试在@Endpoint
之前添加@Component
并且没有区别。
@AndyWilkinson:Indra Basak 已经在下面的评论中回答我,我的失败是基于错误的假设。所以可能你也不能让它工作:)我编辑了我的问题,所以它应该更清楚。 Indra:“文档试图以现有的健康端点为例来解释新的端点基础设施。新的端点 ID 必须是唯一的,并且不应与现有的执行器端点相同。”
【参考方案1】:
更新
新的 Spring Actuator Endpoints 上的 documentation 不是很清晰。它试图以现有的健康端点为例来解释新的端点基础设施。
新的端点 ID 必须是唯一的,并且不应与现有的执行器端点相同。如果尝试将下图示例的 ID 更改为health
,则会出现以下异常:
java.lang.IllegalStateException: Found two endpoints with the id 'health'
上面关于用@Bean
注解声明端点类的注释是正确的。
自定义 health
端点在 Spring Boot 2.0 中没有改变。您仍然需要实现 HealthIndicator
才能添加自定义值。
自定义执行器端点
以下是在 Spring Boot 2.0 中创建自定义 Actuator 端点所需的更改。
型号
包含您的自定义信息的域。
@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class MyHealth
private Map<String, Object> details;
@JsonAnyGetter
public Map<String, Object> getDetails()
return this.details;
我的健康端点
声明myhealth
端点,
@Endpoint(id = "myhealth")
public class MyHealthEndpoint
@ReadOperation
public MyHealth health()
Map<String, Object> details = new LinkedHashMap<>();
details.put("MyStatus", "is happy");
MyHealth health = new MyHealth();
health.setDetails(details);
return health;
我的健康扩展
myhealth
端点的扩展,
@WebEndpointExtension(endpoint = MyHealthEndpoint.class)
public class MyHealthWebEndpointExtension
private final MyHealthEndpoint delegate;
public MyHealthWebEndpointExtension(MyHealthEndpoint delegate)
this.delegate = delegate;
@ReadOperation
public WebEndpointResponse<MyHealth> getHealth()
MyHealth health = delegate.health();
return new WebEndpointResponse<>(health, 200);
执行器配置
将两个新创建的执行器类公开为 bean 的配置,
@Configuration
public class ActuatorConfiguration
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public MyHealthEndpoint myHealthEndpoint()
return new MyHealthEndpoint();
@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
@ConditionalOnBean(MyHealthEndpoint.class)
public MyHealthWebEndpointExtension myHealthWebEndpointExtension(
MyHealthEndpoint delegate)
return new MyHealthWebEndpointExtension(delegate);
应用程序属性
更改为application.yml
,
endpoints:
myhealth:
enabled: true
启动应用程序后,您应该能够访问位于http://<host>:<port>/application/myhealth
的新执行器端点。
您应该会收到类似于如下所示的响应,
"MyStatus": "is happy"
可以在here找到一个完整的工作示例。
【讨论】:
谢谢,它 - 几乎 - 工作 :) 它以某种方式复制了信息,输出是 "details": "MyStatus": "is happy" , "MyStatus": "is happy" 【参考方案2】:提供你自己的@WebEndpoint
like
@Component
@WebEndpoint(id = "acmehealth")
public class AcmeHealthEndpoint
@ReadOperation
public String hello()
return "hello health";
和
-
包括它
将原始/health 映射到/internal/health
将您的自定义端点映射到/health
通过application.properties
:
management.endpoints.web.exposure.include=acmehealth
management.endpoints.web.path-mapping.health=internal/health
management.endpoints.web.path-mapping.acmehealth=/health
这将完全覆盖/health,而不是像自定义HealthIndicator
那样将信息添加到现有/health。问题是,你想要什么,因为@Endpoint(id = "health")
和“我的意图不是创建自定义执行器 myhealth,而是自定义现有的健康执行器”之类的冲突。但是您可以在 AcmeHealthEndpoint 中使用现有的HealthEndpoint
并同时完成这两项工作:
@Component
@WebEndpoint(id = "prettyhealth")
public class PrettyHealthEndpoint
private final HealthEndpoint healthEndpoint;
private final ObjectMapper objectMapper;
@Autowired
public PrettyHealthEndpoint(HealthEndpoint healthEndpoint, ObjectMapper objectMapper)
this.healthEndpoint = healthEndpoint;
this.objectMapper = objectMapper;
@ReadOperation(produces = "application/json")
public String getHealthJson() throws JsonProcessingException
Health health = healthEndpoint.health();
ObjectWriter writer = objectMapper.writerWithDefaultPrettyPrinter();
return writer.writeValueAsString(health);
@ReadOperation
public String prettyHealth() throws JsonProcessingException
return "<html><body><pre>" + getHealthJson() + "</pre></body></html>";
【讨论】:
以上是关于如何使`@Endpoint(id = "health")` 在 Spring Boot 2.0 中工作?的主要内容,如果未能解决你的问题,请参考以下文章
在 Lync UCWA Endpoint ID 中注册应用程序的一般问题
如何使两个span不在同一行显示、如何使两个DIV在同一行显示、我忘记了、不是float:left;这个