6

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

响应示例如下所示:

[
    {
        "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 来提取 self url。

我相信在 Spring 之前一定有更方便的方式来使用 HAL-Response。

谢谢。

4

1 回答 1

3

看看 spring-hateos 的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 的通用支持,但我不知道任何细节。

解决从 url 中提取 id 的问题:

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

{
    "firstname": "Thomas",
    "nachname": "Maier",
    "profession": "http://example.at/professions/1"
}
于 2015-01-23T19:04:20.243 回答