我曾尝试定制春季启动2.0.0.M5健康器的新方法,如下所述: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();
}
}
然而,当我运行HTTP GET到localhost:port/application/health
,我仍然得到标准的默认健康信息。我的代码被完全忽略。
当我使用通过实施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>
春季引导配置application.properties
包含:
endpoints.health.enabled=true
endpoints.autoconfig.enabled=true
endpoints.autoconfig.web.enabled=true
health
,一会出现以下情况例外:
java.lang.IllegalStateException: Found two endpoints with the id 'health'
@Bean
注释声明端点类的评论是正确的。health
终点在春季启动2.0并没有改变。你还必须实现HealthIndicator
添加自定义值。下面是在春季启动2.0创建自定义的执行机构端点所需要的变化。
包含自定义信息的域。
@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);
}
}
配置揭露两个新创建的驱动器类如豆类,
@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。
提供自己的@WebEndpoint
像
@Component
@WebEndpoint(id = "acmehealth")
public class AcmeHealthEndpoint {
@ReadOperation
public String hello() {
return "hello 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彻底,不只是将信息添加到现有的/health,为自定义HealthIndicator
会。问题是,你想要什么,因为@Endpoint(id = "health")
和“我的目的不是创建一个自定义驱动器myhealth,但定制现有的医疗器”之类的碰撞中。但是你可以使用现有的HealthEndpoint
在AcmeHealthEndpoint,完成两个:
@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>";
}
}