在HATEOAS中注册自定义媒体类型无法正常工作。

huangapple go评论71阅读模式
英文:

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);
}

我注意到当输出消息转换器列表时有些奇怪的地方:其中一些重复了两次,而且一个消息转换器中有我的媒体类型(索引为1)。如果我在所有转换器中将supportedMediaType设置为我的类型,getAllContacts()的JSON输出将具有正确的HAL,但我希望自定义类型的注册按照文档中描述的方式工作。我漏掉了什么?

更新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");
  }
}

但仍然没有任何反应。然后我将正常工作的映射器与上述配置提供的映射器进行了比较(手动比较,通过调试),发现没有任何差异。值得注意的是,只有添加了@EnableHyperMediaSupport才能替换映射器。否则不起作用。

英文:

I'm trying to register media type "application/vnd.contactdir.v1+json" but nothing happens and I keep receiving non-HAL json.

Here is my media type provider,

public class ContactDirMediaTypeConfigurationProvider implements MediaTypeConfigurationProvider {

  @Override
  public Class&lt;? extends HypermediaMappingInformation&gt; getConfiguration() {
    return ContactDirMediaTypeConfiguration.class;
  }

  @Override
  public boolean supportsAny(Collection&lt;MediaType&gt; mediaTypes) {
    return true;
  }
}

media type config

@Configuration
public class ContactDirMediaTypeConfiguration implements HypermediaMappingInformation {

  @Override
  public List&lt;MediaType&gt; getMediaTypes() {
    return MediaType.parseMediaTypes(&quot;application/vnd.contactdir.v1+json&quot;);
  }
}

and controller method

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

I noticed something strange when outputted 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. What am I missing?

UPDATE 1

After some more research I figured out that presence of my type in the first TypeConstrainedMapperJackson2HttpMessageConverter only gives a correct result but along with this I've completely got confused.

UPDATE 2

Now I tried to replace ObjectMapper from the first converter with ObjectMapper from the second one and the output became correct. Seems like the problem is in the mapper for converter which supports my media type. I modified its configuration type:

@Configuration
public class ContactDirMediaTypeConfiguration implements HypermediaMappingInformation {

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

  @Override
  public List&lt;MediaType&gt; getMediaTypes() {
    return MediaType.parseMediaTypes(&quot;application/vnd.contactdir.v1+json, application/hal+json&quot;);
  }
}

but still nothing. Then I compared (manually, via debug as I could) working mapper with provided by the config above and found none differences. Worth to note that replacing the mappers works only if @EnableHyperMediaSupport added. In other case it doesn't.

答案1

得分: 2

解决方案是以以下方式进行配置:

@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

英文:

The solution was to make configuration in that way:

@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&lt;MediaType&gt; getMediaTypes() {
    return MediaType.parseMediaTypes(&quot;application/vnd.contactdir.v1+json&quot;);
  }
}

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

huangapple
  • 本文由 发表于 2020年4月5日 06:20:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/61035545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定