我已经将一个Spring Boot应用程序从1.4.x更新到1.5.1,现在Spring Actuator端点返回不同的MIME类型:
例如,/health
现在是 application/vnd.spring-boot.actuator.v1+json
而不是简单的 application/json
了。
我该如何将其更改回来?
我已经将一个Spring Boot应用程序从1.4.x更新到1.5.1,现在Spring Actuator端点返回不同的MIME类型:
例如,/health
现在是 application/vnd.spring-boot.actuator.v1+json
而不是简单的 application/json
了。
我该如何将其更改回来?
端点返回符合客户端请求所能接受的内容类型。如果客户端发送了一个要求使用application/json
的Accept
头,则会收到相应的JSON响应:
Accept: application/json
回应https://stackoverflow.com/users/2952093/kap的评论(我的声望值不够高,无法发表评论):当使用Firefox检查返回JSON的端点时,我使用Add-on JSONView。在设置中有一个选项可以指定替代的JSON内容类型,只需添加application/vnd.spring-boot.actuator.v1+json
,您就可以在浏览器内以漂亮的格式打印查看返回的JSON。
自从SpringBoot 2.0.x版本以后,实现EndpointHandlerMappingCustomizer
的建议解决方案已经不再适用。
好消息是,现在的解决方案更简单了。
需要提供Bean EndpointMediaTypes
。默认情况下,它由SpringBoot类WebEndpointAutoConfiguration
提供。
提供您自己的可以像这样:
@Configuration
public class ActuatorEndpointConfig {
private static final List<String> MEDIA_TYPES = Arrays
.asList("application/json", ActuatorMediaType.V2_JSON);
@Bean
public EndpointMediaTypes endpointMediaTypes() {
return new EndpointMediaTypes(MEDIA_TYPES, MEDIA_TYPES);
}
}
你可能已经注意到,1.5.x版本中执行器的内容类型已发生变化。
如果你在"Accept:"头中输入"application/json",你应该会得到通常的内容类型。
但如果你没有任何修改客户端的方法,这段代码将返回健康信息(不包括细节)和原始内容类型(即1.4.x版本的方式)。
@RestController
@RequestMapping(value = "/health", produces = MediaType.APPLICATION_JSON_VALUE)
public class HealthController {
@Inject
HealthEndpoint healthEndpoint;
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Health > health() throws IOException {
Health health = healthEndpoint.health();
Health nonSensitiveHealthResult = Health.status(health.getStatus()).build();
if (health.getStatus().equals(Status.UP)) {
return ResponseEntity.status(HttpStatus.OK).body(nonSensitiveHealthResult);
} else {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(nonSensitiveHealthResult);
}
}
}
配置(移除现有健康状况)
endpoints.health.path: internal/health
基于https://github.com/spring-projects/spring-boot/issues/2449中的代码(该代码完全移除了新类型,但仍然有效),我得出以下结论:
@Component
public class ActuatorCustomizer implements EndpointHandlerMappingCustomizer {
static class Fix extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
Object attribute = request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
if (attribute instanceof LinkedHashSet) {
@SuppressWarnings("unchecked")
LinkedHashSet<MediaType> lhs = (LinkedHashSet<MediaType>) attribute;
if (lhs.remove(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON)) {
lhs.add(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON);
}
}
return true;
}
}
@Override
public void customize(EndpointHandlerMapping mapping) {
mapping.setInterceptors(new Object[] {new Fix()});
}
}
它将新的供应商媒体类型放在最后,这样当没有指定内容时,它将在所有执行器端点中使用 application/json
。
已测试与spring-boot 1.5.3。
[application/vnd.spring-boot.actuator.v1+json, application/json]
切换为 [application/json, application/vnd.spring-boot.actuator.v1+json]
。以下方法同样有效(并且可能更少令人困惑):lhs.remove(ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON); lhs.add(MediaType.APPLICATION_JSON);
- crusyapplication/json
之后,因为我想使用默认浏览器获取 json。由于 LinkedHashSet
保持插入顺序,我只需将其删除并重新添加以将其排序到后面。使用 if
来确保我不会修改一开始没有这种新类型的东西。 - zaplmapping.setInterceptors(new Fix())
。 - jerrybapplication/vnd.spring-boot.actuator.v1+json
,您可以安装此插件:json-content-type-override。它将把包含“json”的内容类型转换为“application/json”。
application/vnd.spring-boot.actuator.v1+json
这种JSON类型。你可以使用JSONView插件,并勾选两个选项:在HTTP请求头中包含"application/json"
和使用Firefox内置的JSON查看器。这样浏览器就会请求application/json
类型的响应,同时JSONView不会干扰响应的读取,Firefox会将其作为普通的JSON读取。 - jihor