使用RestTemplate消耗Spring Hateoas Rest服务

时间:2015-01-02 14:16:57

标签: java client resttemplate spring-hateoas hal

我有两个应用程序,一个名为 bar ,它为我提供了HAL格式的资源。另一个是 bcm 来使用该服务。

回复示例 bar 如下所示:

[
    {
        "name":"Brenner/in",
        "_links":{
            "self":{
                "href":"..host/bbsng-app-rest/betrieb/15"
            }
        }
    },
    {
        "name":"Dienstleistungshelfer/in HW",
        "_links":{
            "self":{
                "href":"..host/bbsng-app-rest/betrieb/4"
            }
        }
    },
    {
        ...

现在我尝试使用Spring RestTemplate从 bcm 中消费它。我的解决方案有效,但我不满意这个解决方案,我想有一个更干净的方式。

我的客户端代码消耗RestService看起来像:

@Autowired private RestTemplate template;

@Override
@SuppressWarnings("unchecked")
public BerufListe findeAlleBerufe() {
    final BerufListe berufListe = new BerufListe();

    final ResponseEntity<List> entity = template.getForEntity(LinkUtils.findBeruf(), List.class);

    if (OK.equals(entity.getStatusCode())) {
        final List<LinkedHashMap> body = entity.getBody();
        for (final LinkedHashMap map : body) {
            final LinkedHashMap idMap = (LinkedHashMap) map.get("_links");
            String id = remove(String.valueOf(idMap.get("self")), "href=");
            id = remove(id, "{");
            id = remove(id, "}");
            final String name = String.valueOf(map.get("name"));
            final Beruf beruf = new Beruf(id, name);
            berufListe.add(beruf);
        }
    }

    return berufListe;
}

你看到的代码很难看。其中之一是,我的收藏品没有任何泛型。另一点,我得到的Resource_ID非常复杂,我多次使用StringUtils.remove来提取自己的URL。

我确信必须有一种更方便的方法来消耗Spring的HAL-Response。

谢谢你。

1 个答案:

答案 0 :(得分:3)

看一下spring-hateaos的Resource课程。

它提供了从响应中提取链接的方法。 但是,由于RestTemplate要求您将类作为变量提供,除了创建所需实体的子类并将其用于RestTemplate之外,我没有找到不同的方法。

您的代码可能如下所示:

public class BerufResource extends Resource<Beruf> { }

BerufResource resource = template.getForEntity("http://example.at/berufe/1", BerufResource.class);
Beruf beruf = resource.getContent();
// do something with the entity

如果要请求完整列表,则需要将实体的数组版本传递给RestTemplate:

BerufResource[] resources = template.getForEntity("http://example.at/berufe", BerufResource[].class);

List<BerufResource> berufResources = Arrays.asList(resources);
for(BerufResource resource : berufResources) {
    Beruf beruf = resource.getContent();
}

不幸的是,我们不能编写Resource<Beruf>.class来破坏泛型类的整个目的,因为我们需要再次为每个实体创建一个子类。其背后的原因称为类型擦除。我曾在某处读到他们计划为RestTemplate引入通用支持,但我不知道任何细节。

解决从网址中提取id的问题:

我建议在客户端使用不同的模型,并用字符串替换id字段的类型,并将整个url存储在其中。这样,您可以随时轻松地重新获取整个实体,而不需要自己构建URL。如果您计划向API提交POST请求,则无论如何您都需要URL,因为spring-hateaos要求您发送链接而不是ID。 典型的POST请求可能如下所示:

{
    "firstname": "Thomas",
    "nachname": "Maier",
    "profession": "http://example.at/professions/1"
}