在 HATEOAS 中注册自定义媒体类型不起作用

Registering a custom mediatype in HATEOAS does not work

我正在尝试注册媒体类型 "application/vnd.contactdir.v1+json" 但没有任何反应,我一直收到非 HAL json。

这是我的媒体类型提供商,

public class ContactDirMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider {

  @Override
  public Class<? extends HypermediaMappingInformation> getConfiguration() {
    return ContactDirMediaTypeConfiguration.class;
  }

  @Override
  public boolean supportsAny(Collection<MediaType> mediaTypes) {
    return true;
  }
}

媒体类型配置

@Configuration
public class ContactDirMediaTypeConfiguration implements HypermediaMappingInformation {

  @Override
  public List<MediaType> getMediaTypes() {
    return MediaType.parseMediaTypes("application/vnd.contactdir.v1+json");
  }
}

和控制器方法

 @GetMapping(path = "/contacts",
      produces = {"application/vnd.contactdir.v1+json", "application/hal+json"})
  public ResponseEntity<CollectionModel<ContactDto>> getAllContacts() {
    List<ContactDto> list = contactListService.getAllContacts();
    CollectionModel<ContactDto> collectionModel = linkAppender.appendLinks(list);
    collectionModel.add(
        linkTo(methodOn(ContactListController.class).getAllContacts()).withSelfRel());
    return new ResponseEntity<>(collectionModel, HttpStatus.OK);
  }

我在输出时发现了一些奇怪的东西the list of message converters: some of them repeated twice and one had my media type (with index 1). And If I set supportedMediaType to my type in all of them, json output of getAllContacts() will have correct HAL but I want custom type registration to work as it's described in the documentation。我错过了什么?

更新 1

经过更多研究后,我发现我的类型在第一个 TypeConstrainedMapperJackson2HttpMessageConverter 中的存在只给出了正确的结果,但与此同时我完全感到困惑。

更新 2

现在我尝试用第二个转换器中的 ObjectMapper 替换第一个转换器中的 ObjectMapper,并且输出变得正确。似乎问题出在支持我的媒体类型的转换器的映射器中。我修改了它的配置类型:

@Configuration
public class ContactDirMediaTypeConfiguration implements HypermediaMappingInformation {

  @Override
  public Module getJacksonModule() {
    return new Jackson2HalModule();
  }

  @Override
  public List<MediaType> getMediaTypes() {
    return MediaType.parseMediaTypes("application/vnd.contactdir.v1+json, application/hal+json");
  }
}

但还是一无所获。然后我比较(手动,尽可能通过调试)工作映射器与上面的配置提供的,发现 none 差异。值得注意的是,仅当添加了 @EnableHyperMediaSupport 时,替换映射器才有效。在其他情况下它没有。

解决方案是这样配置:

@Configuration
public class ContactDirMediaTypeConfiguration implements HypermediaMappingInformation {

  @Override
  public Module getJacksonModule() {
    return new Jackson2HalModule();
  }

  @Override
  public ObjectMapper configureObjectMapper(ObjectMapper mapper) {

    mapper.registerModule(getJacksonModule());
    mapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(new EvoInflectorLinkRelationProvider(),
        CurieProvider.NONE, MessageResolver.DEFAULTS_ONLY));

    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

    return mapper;
  }

  @Override
  public List<MediaType> getMediaTypes() {
    return MediaType.parseMediaTypes("application/vnd.contactdir.v1+json");
  }
}

来源:https://github.com/spring-projects/spring-hateoas/issues/1253#issuecomment-608973523