消耗Spring Hateoas Pageable
我有一个使用HAteoas的Rest-Service,以前没有分页的工作。 现在我正在制作可分页的Json。 我用Spring-Hateoas的开箱即用function做到了这一点。 但现在我正在坚持消耗它,我想它确实没有很好的记录,如果是的话。
我的JSON如下所示:
{ "_embedded": { "vertragResourceList": [ { "identifier": 728, "auszubildender": "Rumm", "beruf": "Landwirt/in", "betrieb": "Mitterbauer Johann", "betriebsNummer": "e12d0949-67ae-4134-9dc2-fb67758b6b16", "zustaendigeStelle": "Irgendwo", "beginn": 529887600000, "status": "RECENT", "fachrichtung": null, "schwerpunkt": "Grünland oder Ackergras", "ende": 623113200000, "_links": { "self": { "href": "http://localhost:8080/bbsng-app-rest/vertrag/728" } } }, { "identifier": 803, "auszubildender": "Gossen", "beruf": "Landwirt/in", "betrieb": "Beer Johann", "betriebsNummer": "d5a20cb9-7273-4b75-85bd-f8e7d6a843c4", "zustaendigeStelle": "Woanders", "beginn": 278118000000, "status": "RECENT", "fachrichtung": null, "schwerpunkt": "Ackerfutterbau", "ende": 339116400000, "_links": { "self": { "href": "http://localhost:8080/bbsng-app-rest/vertrag/803" } } } ] }, "page": { "size": 2, "totalElements": 1000, "totalPages": 500, "number": 5 } }
====
但是现在我的列表是“_embedded”,所以我怎样才能以最方便的方式使用它。 我更喜欢Spring-Hateoas或类似的开箱即用的解决方案。
我的代码之前的工作方式如下( Json在!!!之前没有包装在_embedded / vertragResourceList中 )。
@Override @SuppressWarnings({ "unchecked", "rawtypes" }) public VertragsListe findeAlleVertraege(final Integer firstDataSet, final Integer lastDataSet, final VertragDTFilter vertragsFilter, final VertragDTSorting vertragSorting) { final VertragsListe vertragsListe = new VertragsListe(); final String url = LinkUtils.findeVertrag(firstDataSet, lastDataSet, vertragsFilter, vertragSorting); final ResponseEntity entity = template.getForEntity(url, List.class); if (OK.equals(entity.getStatusCode())) { final List body = entity.getBody(); for (final LinkedHashMap map : body) { vertragsListe.add(getPopulatedVertrag(vertragsListe, map)); } } return vertragsListe; }
堆栈跟踪:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@e89d61c; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@e89d61c; line: 1, column: 1]
=====
编辑:
对应的Resourceclass看起来像这样(Serverside和Clientside !!!):
public class VertragPagedResources extends PagedResources { @SuppressWarnings("unchecked") public VertragPagedResources(final Collection content, final PageMetadata metadata) { super(content, metadata, CollectionUtils.EMPTY_COLLECTION); } public VertragPagedResources() { super(); } }
在Clientside我现在改变了:
@Autowired private RestTemplate template; @Override public VertragPagedResources findeAlleVertraege(final Integer firstDataSet, final Integer lastDataSet, final VertragDTFilter vertragsFilter, final VertragDTSorting vertragSorting) { final String url = LinkUtils.findeVertrag(firstDataSet, lastDataSet, vertragsFilter, vertragSorting); final ResponseEntity entity = template.getForEntity(url, VertragPagedResources.class); if (OK.equals(entity.getStatusCode())) { return entity.getBody(); } return new VertragPagedResources(); }
现在我没有任何例外,但内容是空的。 正确填充的唯一内容是来自可分页的信息(numberOfReturned Datasets,pageSize等)。 内容为空列表!!! 在调试时,我在浏览器中尝试给定的URL,然后JSON看起来像上面提到的那样。
VertragResource(客户端和服务器):
public class VertragResource extends IdentifierResourceSupport { @NotNull private String auszubildender; @NotNull private String beruf; @NotNull private String betrieb; @NotNull private String betriebsNummer; @NotNull private String zustaendigeStelle; @NotNull private Calendar beginn; @NotNull private String status; private String fachrichtung; private String schwerpunkt; private Calendar ende; // GETTER & SETTER ....
控制器服务器端:
@RequestMapping(method = GET, produces = MediaType.APPLICATION_JSON_VALUE) public HttpEntity showAll( /* PARAMS */ ) { // FILTER ... final VertragFilter filter = new VertragFilter(); // FILL FILTER // SORTING ... final VertragSorting sorting = new VertragSorting(/* BLA */) // COMPUTE ... final VertragResourceAssembler assembler = new VertragResourceAssembler(); final List alleVertrage = service.findeAlleVertraege(/* BLA */); final List resources = assembler.toResources(alleVertrage); // final long totalElements = service.zaehleAlleVertraege(filter); final long size = Math.min(displayLength, totalElements); final long totalPages = totalElements / size; final PageMetadata pageMetadata = new PageMetadata(displayLength, displayStart, totalElements, totalPages); final VertragPagedResources pagedResources = new VertragPagedResources(resources, pageMetadata); return new HttpEntity(pagedResources, headerTotalNumberOfData()); }
====
IdentifierResourceSupport:
public class IdentifierResourceSupport extends ResourceSupport { private Long identifier; public Long getIdentifier() { return identifier; } public void setIdentifier(Long identifier) { this.identifier = identifier; } }
=====
编辑2:
我现在做了什么,我将Spring-Boot从1.2.1切换回1.1.10。 现在我在尝试相同时遇到exception,似乎Spring-Boot 1.2.1隐藏了exception:
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "_embedded" (class at.compax.bbsng.client.mvc.client.resource.VertragPagedResources), not marked as ignorable (3 known properties: "links", "content", "page"]) at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@62532c56; line: 1, column: 15] (through reference chain: at.compax.bbsng.client.mvc.client.resource.VertragPagedResources["_embedded"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_embedded" (class at.compax.bbsng.client.mvc.client.resource.VertragPagedResources), not marked as ignorable (3 known properties: "links", "content", "page"]) at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@62532c56; line: 1, column: 15] (through reference chain: at.compax.bbsng.client.mvc.client.resource.VertragPagedResources["_embedded"])
好的,
我现在得到了解决方案。
首先,Spring Boot 1.2.1中有一个BUG。 就像在EDIT2中提到的那样。 Spring-Boot 1.1.10抛出exception,因为它无法映射_embedded中的内容。 这就是为什么我的内容保持空白。 Spring Boot 1.2.1只是让它没有任何提示作为例外。 降级到1.1.10给了我一些暗示。
那么改变的后果是什么:
Serverside上的控制器:
@RequestMapping(method = GET, produces = "application/hal+json") public HttpEntity showAll( /* PARAMS */ ) { // LIKE CODE IN QUESTION ... return new HttpEntity (pagedResources); }
====
RestTemplate配置:
然后,您需要配置Resttemplate以处理HAL格式。
@Bean public RestTemplate restTemplate() { final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Jackson2HalModule()); final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); converter.setObjectMapper(mapper); return new RestTemplate(Collections.> singletonList(converter)); }
客户端代码与第一个问题编辑保持一致!