【问题标题】:How to simply enable HAL+JSON object mapping with Spring Restemplate如何使用 Spring Resttemplate 简单地启用 HAL+JSON 对象映射
【发布时间】:2016-04-20 00:31:46
【问题描述】:

我一直在努力弄清楚如何在我的客户端中简单地启用这种功能以响应 HAL+JSON 请求。如果我有特定的资源,我可以获取要绑定的属性,但我真的希望 href 采用易于使用的格式,这样我就可以懒惰地获取它们。

Organization[] orgs = restTemplate.getForObject("http://myservice/organizations",Organizations[].class);

组织 org = restTemplate.getForObject("http://myservice/organizations/1",Organization.class);

鉴于以下 HAL 和实体:

{
    "_embedded": {
        "af:organizations": [
            {
                "name": "First Company",
                "description": "Some company",
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/hal/organizations/1"
                    },
                    "af:workers": {
                        "href": "http://localhost:8080/hal/organizations/1/workers",
                        "title": "Cancel an order"
                    }
                }
            },
            {
                "name": "Second Company",
                "description": "Someplace we all used to work",
                "_links": {
                    "self": {
                        "href": "http://localhost:8080/hal/organizations/2"
                    },
                    "af:workers": {
                        "href": "http://localhost:8080/hal/organizations/2/workers",
                        "title": "All the little ants on your farm"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/hal/organizations"
        },
        "profile": {
            "href": "http://localhost:8080/hal/profile/organizations"
        },
        "curies": [
            {
                "href": "/custom/docs/{rel}.txt",
                "name": "af",
                "templated": true
            }
        ]
    }
}

实体

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@NoArgsConstructor
@EqualsAndHashCode
@AllArgsConstructor
public class Organization {

    private String name;

    private String description;

    @JsonProperty("_links")
    private Map<String, Link> links;

}

配置(这是我的第三次尝试。这只是我目前的尝试)

@Configuration
@EnablePluginRegistries(RelProvider.class)
@PropertySource("classpath:ant-farm-client.properties")
public class AntFarmClientConfig {

    @Value("${server.url}")
    private String base;


    private static final boolean EVO_PRESENT =
            ClassUtils.isPresent("org.atteo.evo.inflector.English", null);

    @Autowired
    private PluginRegistry<RelProvider, Class<?>> relProviderRegistry;


    @Bean
    public ObjectMapper jacksonObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return objectMapper;
    }

    @Bean
    public MappingJackson2HttpMessageConverter jsonConverter() {
        MappingJackson2HttpMessageConverter jacksonConverter = new
                MappingJackson2HttpMessageConverter();
        jacksonConverter.setSupportedMediaTypes(Arrays.asList(MediaType.valueOf("application/json")));
        jacksonConverter.setObjectMapper(jacksonObjectMapper());
        return jacksonConverter;
    }

    @Bean
    public CurieProvider curieProvider() {
        return new DefaultCurieProvider("af", new UriTemplate("http://schema.org/{rel}"));
    }


    @Bean
    MessageSourceAccessor accessor(ApplicationContext context) {
        return new MessageSourceAccessor(context);
    }
    @Bean
    public RestOperations template(ObjectMapper mapper,MappingJackson2HttpMessageConverter halConverter ) {
        RestTemplate restTemplate = new RestTemplate();

        DefaultUriTemplateHandler handler = new DefaultUriTemplateHandler();
        handler.setBaseUrl(base);
        restTemplate.setUriTemplateHandler(handler);

        restTemplate.getMessageConverters().add(halConverter);
        return restTemplate;
    }

    @Bean
    public MappingJackson2HttpMessageConverter halConverter(MessageSourceAccessor accessor) {
        CurieProvider curieProvider = curieProvider();

        RelProvider relProvider = new DelegatingRelProvider(relProviderRegistry);
        ObjectMapper halObjectMapper = new ObjectMapper();

        halObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        halObjectMapper.registerModule(new Jackson2HalModule());
        halObjectMapper.setHandlerInstantiator(new
                Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider,accessor));

        MappingJackson2HttpMessageConverter halConverter = new  MappingJackson2HttpMessageConverter();
        halConverter.setSupportedMediaTypes(Arrays.asList(MediaTypes.HAL_JSON));
        halConverter.setObjectMapper(halObjectMapper);

        return halConverter;
    }

    @Bean
    RelProvider defaultRelProvider() {
        return EVO_PRESENT ? new EvoInflectorRelProvider() : new DefaultRelProvider();
    }

    @Bean
    RelProvider annotationRelProvider() {
        return new AnnotationRelProvider();
    }

【问题讨论】:

  • 只是为了明确一点:您想从 Organization 实例内部访问链接列表,是这样吗?
  • 我已经做出改变来获得它。我很想用 Jayway 来瘦身。我将根据更改更新代码。

标签: spring-data-rest spring-hateoas


【解决方案1】:

我会尝试从 RestTemplate 中获取 Resources&lt;Resource&lt;Organization&gt;&gt;。外部Resources 将包含全局链接,然后内容中的每个Resource 都包含项目链接。

我不会创建自己的 ObjectMapper - spring hateoas 提供了一个。重要的是您的 RestTemplate 具有可以转换 application/hal+jsonHttpMessageConverter

这篇文章展示了一个这样做的例子https://dzone.com/articles/spring-resttemplate-linked

目前我无法亲自尝试,所以我只能为您提供这些未经检验的想法。

【讨论】:

  • 您的 cmets 赚钱了。我现在正在走这条路,并试图弄清楚如何最好地使用 API。我也一直在消化这一点:docs.spring.io/spring-hateoas/docs/current/reference/html 但是,我正在尝试弄清楚当我启用文档的curying 时如何让它工作。
  • 当我扩展“ResourceSupport”时,已经有了“链接”,我实际上并没有将它们编组。
  • 正如我所说 - 我只是在猜测 - 但如果你在 github 上有复制案例,我会很乐意尝试一件事或另一件事
猜你喜欢
  • 2018-05-16
  • 2017-02-20
  • 2015-05-07
  • 2016-11-25
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多