【问题标题】:Spring HATEOAS links return in HAL format for single objects, and the spec format for an array of objectsSpring HATEOAS 链接以 HAL 格式返回单个对象,以及对象数组的规范格式
【发布时间】:2017-03-07 20:27:42
【问题描述】:

我正在使用 Spring HATEOAS 0.20(也尝试过 0.23)并且在返回单个对象与对象数组时似乎存在非常奇怪的行为。返回单个对象时,生成的 JSON 返回通过 HAL 规范格式化的 HATEOAS 链接(“_links”,我不想要):

{
  "_Id": 161,
  ...
  "_links": {
    "self": {
      "href": "http://localhost:8080/library/161"
    }
  }
}

返回对象数组时,生成的 JSON 会返回规范格式的 HATEOAS 链接(“链接”,我确实想要):

[
  {
    "_Id": 277,
    ...
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/library/277"
      }
    ]
  }
]

我没有指定@EnableHypermediaSupport,所以不应该支持HAL。但是,当返回单个对象时,我仍然会得到 HAL 格式。

有人知道为什么会这样吗? 需要做什么才能通过 HATEOAS 规范返回带有 HATEOAS 链接的单个对象?

===== 根据请求更新发布以获取更多信息 =====

如果我使用以下代码返回 JSON 负载,我会得到 HAL 链接:

//
//------------------- Get Single Membership As Single Object ----------------------------------------------
//
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = REQUEST_GET_MEMBERSHIP, method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<MembershipResource> getMembership(@PathVariable("membership-id") Integer membershipId) {
    Membership membership = membershipRepository.findOne(membershipId);

    if (membership == null) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("error", "Membership with ID of " + membershipId + " does not exist.");
        return new ResponseEntity<MembershipResource>(headers, HttpStatus.NOT_FOUND);
    }

    MembershipResourceAssembler assm = new MembershipResourceAssembler();
    MembershipResource membershipResource = assm.toResource(membership);

    System.out.println("membership id: " + membership.getId());
    return new ResponseEntity<MembershipResource>(membershipResource, HttpStatus.OK);
}

以上会产生HAL规范风格的链接:

{
  "_Id": 277,
  "member": {
    "_Id": 112,
    "title": "Mr.",
    "firstName": "ABC",
    "middleName": "",
    "lastName": "XYZ",
    "active": true,
    "_links": {
      "self": {
        "href": "http://localhost:8080/members/112"
      }
    }
  },
  "membershipTermType": "2016",
  "card": {
    "_Id": 27,
    "name": "27",
    "graphicUrl": "",
    "number": 27,
  },
  "active": false,
  "paid": true,
  "renewal": true,
  "termsAndConditionsAcknowledged": true,
  "_links": {
    "self": {
      "href": "http://localhost:8080/memberships/277"
    }
  }
}

如果我修改方法以返回单个成员的列表,则返回的 JSON 负载带有 HATEOAS 规范链接:

//
//------------------- Get Single Membership As List --------------------------------------------------------
//
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = REQUEST_GET_MEMBERSHIP, method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<List<MembershipResource>> getMembership(@PathVariable("membership-id") Integer membershipId) {
    Membership membership = membershipRepository.findOne(membershipId);

    if (membership == null) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("error", "Membership with ID of " + membershipId + " does not exist.");
        return new ResponseEntity<List<MembershipResource>>(headers, HttpStatus.NOT_FOUND);
    }

    MembershipResourceAssembler assm = new MembershipResourceAssembler();
        MembershipResource membershipResource = assm.toResource(membership);

    ArrayList<MembershipResource> list = new ArrayList<MembershipResource>();
    list.add(membershipResource);

    System.out.println("membership id: " + membership.getId());
    return new ResponseEntity<List<MembershipResource>>(list, HttpStatus.OK);
}

上面会产生HATEOAS-specification风格的链接:

[
  {
    "_Id": 277,
    "member": {
      "_Id": 112,
      "title": "Mr.",
      "firstName": "ABC",
      "middleName": "",
      "lastName": "XYZ",
      "active": true,
      "links": [
        {
          "rel": "self",
          "href": "http://localhost:8080/members/112"
        }
      ]
    },
    "membershipTermType": "2016",
    "card": {
      "_Id": 27,
      "name": "27",
      "graphicUrl": "",
      "number": 27,
      "links": []
    },
    "active": false,
    "renewal": true,
    "paid": true,
    "termsAndConditionsAcknowledged": true,
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/memberships/277"
      }
    ]
  }
]

有人知道为什么会这样吗? 需要做什么才能通过 HATEOAS 规范返回带有 HATEOAS 链接的单个对象?

【问题讨论】:

  • 当你请求 HAL 时,你会得到它。您的请求看起来如何?你的控制器方法呢?
  • @zeroflagL - 我已经修改了我的帖子来回答你的问题。谢谢!
  • 不同的行为很可能源于这样一个事实:在一种情况下,ResourceSupport 的实例被返回,而在另一种情况下则没有(只有List)。你使用 Spring Boot 吗?
  • 是的,我目前正在使用 Spring Boot。
  • 然后您可以尝试在您的应用程序中添加@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class) 或在您的属性文件中添加spring.hateoas.use-hal-as-default-json-media-type=false

标签: arrays json spring-hateoas


【解决方案1】:

由于我使用 Spring Boot 作为我的应用程序服务器,@zeroflagL 建议我尝试在您的应用程序中添加 @EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class) 或在属性文件中添加 spring.hateoas.use-hal-as-default-json-media-type=false

@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class) 的配置注释添加到我的应用程序类解决了这个问题。

【讨论】:

  • 我无法使用 spring boot 1.4.3.RELEASE 让它工作。有什么想法吗?
  • @AlexWhite @RequestMapping(value = "/someresource",produces ={"application/collection+json" }) 添加到控制器似乎可以解决问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 2021-07-18
  • 2015-01-18
  • 2020-09-27
  • 2020-03-30
相关资源
最近更新 更多