Spring-hateoas 客户端与 spring-boot-data-rest 不兼容?

Spring-hateoas client not compatible with spring-boot-data-rest?

为了尝试了解 spring 生态系统,我正在用各种零件构建一些玩具项目。

我有一个 spring-boot-data-rest 服务按预期工作 (code here) and I am building a spring-boot and spring-hateoas client to access it (code here)

但出于某种原因,我不明白客户端看不到服务器拥有的链接。

这是 JSON 服务的样子:

{
    "firstName": "Alice",
    "lastName": "Foo",
    "_links": {
        "self": {
            "href": "http://localhost:8080/people/1"
        },
        "person": {
            "href": "http://localhost:8080/people/1"
        }
    }
}

这是客户端用来查询服务的代码:

    //now use a GET to get it back
    ResponseEntity<Resource<Person>> getResult = rest.exchange(
            "http://localhost:8080/people/1", HttpMethod.GET, null,
            new ParameterizedTypeReference<Resource<Person>>() {
            });

    //check the links on the response
    log.info("getResult "+getResult);
    log.info("getResult.getBody"+getResult.getBody());
    //uh oh, no links...
    log.info("getResult.getLink(\"self\")"+getResult.getBody().getLink("self"));
    log.info("getResult.getLink(\"self\").getHref()"+getResult.getBody().getLink("self").getHref());

我正在使用 Spring boot 1.4。0.BUILD-SNAPSHOT 版本。

这是我的代码的问题还是某处的错误?有什么解决办法吗?

您没有启用对 HAL 的支持。您的服务器使用 Spring Data REST,默认为 uses HAL。另一方面,客户端对 HAL 一无所知。您可以通过添加 @EnableHypermediaSupport:

来添加支持
@SpringBootApplication
@EnableHypermediaSupport(type = HypermediaType.HAL)
public class Application {

正如@zeroflagL 所指出的,客户不知道 HAL。

解决方案比较复杂,借鉴 的答案,向 RestTemplate 注册一个额外的 HTTPMessageConverter 来处理 "application/hal+json" 内容。

    RestTemplate rest = new RestTemplate();

    //need to create a new message converter to handle hal+json
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    mapper.registerModule(new Jackson2HalModule());
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
    converter.setObjectMapper(mapper);

    //add the new converters to the restTemplate
    //but make sure it is BEFORE the exististing converters
    List<HttpMessageConverter<?>> converters = rest.getMessageConverters();
    converters.add(0,converter);
    rest.setMessageConverters(converters);