2016-01-07 85 views
12

我們的REST API正在返回Pages中的結果。這裏是一個控制器的例子帶分頁API的Spring RestTemplate

@RequestMapping(value = "/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8") 
@ResponseStatus(HttpStatus.OK) 
public Page<MyObject> findAll(Pageable pageable) { 
    ... 
} 

有沒有簡單的方法來使用RestTemplate API?

如果我們做

ParameterizedTypeReference<Page<MyObject>> responseType = new ParameterizedTypeReference<Page<MyObject>>() { }; 

ResponseEntity<Page<MyObject>> result = restTemplate.exchange(url, HttpMethod.GET, null/*httpEntity*/, responseType); 

List<MyObject> searchResult = result.getBody().getContent(); 

它拋出一個異常

org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Can not construct instance of org.springframework.data.domain.Page, 
problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information at [Source: [email protected]; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of org.springframework.data.domain.Page, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information 

預先感謝您

回答

6

改變了代碼讀取REST API響應爲;

ParameterizedTypeReference<RestResponsePage<MyObject>> responseType = new ParameterizedTypeReference<RestResponsePage<MyObject>>() { }; 

ResponseEntity<RestResponsePage<MyObject>> result = restTemplate.exchange(url, HttpMethod.GET, null/*httpEntity*/, responseType); 

List<MyObject> searchResult = result.getBody().getContent(); 

這裏是我的RestResponsePage

package com.basf.gb.cube.seq.vaadinui.util; 

import java.util.ArrayList; 
import java.util.List; 

import org.springframework.data.domain.PageImpl; 
import org.springframework.data.domain.Pageable; 

public class RestResponsePage<T> extends PageImpl<T>{ 

    private static final long serialVersionUID = 3248189030448292002L; 

    public RestResponsePage(List<T> content, Pageable pageable, long total) { 
    super(content, pageable, total); 
    // TODO Auto-generated constructor stub 
    } 

    public RestResponsePage(List<T> content) { 
    super(content); 
    // TODO Auto-generated constructor stub 
    } 

    /* PageImpl does not have an empty constructor and this was causing an issue for RestTemplate to cast the Rest API response 
    * back to Page. 
    */ 
    public RestResponsePage() { 
    super(new ArrayList<T>()); 
    } 

} 
+0

爲什麼傳入null httpEntity? null/* httpEntity */ –

+0

這不會返回正確的頁數或結果總數。 – ACOMIT001

0

發佈對我來說沒有工作的解決方案創建的類,因爲總要素設定不正確。我使用委託模式實現了頁面,該模式對我很有用。這裏是工作代碼:

import org.springframework.core.convert.converter.Converter; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageImpl; 
import org.springframework.data.domain.Pageable; 
import org.springframework.data.domain.Sort; 

import java.util.ArrayList; 
import java.util.Iterator; 
import java.util.List; 

public class RestPage<T> implements Page<T> { 
    private PageImpl<T> pageDelegate = new PageImpl<>(new ArrayList<>(0)); 

    public List<T> getContent() { 
     return pageDelegate.getContent(); 
    } 

    public int getNumber() { 
     return pageDelegate.getNumber(); 
    } 

    public int getNumberOfElements() { 
     return pageDelegate.getNumberOfElements(); 
    } 

    public int getSize() { 
     return pageDelegate.getSize(); 
    } 

    public Sort getSort() { 
     return pageDelegate.getSort(); 
    } 

    public long getTotalElements() { 
     return pageDelegate.getTotalElements(); 
    } 

    public int getTotalPages() { 
     return pageDelegate.getTotalPages(); 
    } 

    public boolean hasContent() { 
     return pageDelegate.hasContent(); 
    } 

    public boolean hasNext() { 
     return pageDelegate.hasNext(); 
    } 

    public boolean hasPrevious() { 
     return pageDelegate.hasPrevious(); 
    } 

    public boolean isFirst() { 
     return pageDelegate.isFirst(); 
    } 

    public boolean isLast() { 
     return pageDelegate.isLast(); 
    } 

    public Iterator<T> iterator() { 
     return pageDelegate.iterator(); 
    } 

    public <S> Page<S> map(Converter<? super T, ? extends S> converter) { 
     return pageDelegate.map(converter); 
    } 

    public Pageable nextPageable() { 
     return pageDelegate.nextPageable(); 
    } 

    public Pageable previousPageable() { 
     return pageDelegate.previousPageable(); 
    } 

    public void setContent(List<T> content) { 
     pageDelegate = new PageImpl<>(content, null, getTotalElements()); 
    } 


    public void setTotalElements(int totalElements) { 
     pageDelegate = new PageImpl<>(getContent(), null, totalElements); 
    } 

    public String toString() { 
     return pageDelegate.toString(); 
    } 
} 
+0

這隻能處理1-arg構造函數的情況。如果你有一個3參數的構造函數,那麼這是沒用的。 – cst1992

+1

其他字段未填充除totalElements和content之外的上述代碼。 – MasterCode

6

在上面展開,但不需要實現每個屬性。

import com.fasterxml.jackson.annotation.JsonCreator; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import org.springframework.data.domain.PageImpl; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.domain.Pageable; 

import java.util.ArrayList; 
import java.util.List; 

public class RestPageImpl<T> extends PageImpl<T>{ 

    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) 
    public RestPageImpl(@JsonProperty("content") List<T> content, 
         @JsonProperty("number") int page, 
         @JsonProperty("size") int size, 
         @JsonProperty("totalElements") long total) { 
     super(content, new PageRequest(page, size), total); 
    } 

    public RestPageImpl(List<T> content, Pageable pageable, long total) { 
     super(content, pageable, total); 
    } 

    public RestPageImpl(List<T> content) { 
     super(content); 
    } 

    public RestPageImpl() { 
     super(new ArrayList()); 
    } 
} 
2

沒有必要實施Page。您只需在ParameterizedTypeReference中使用PagedResources<T>作爲類型。

所以,如果你的服務回報響應類似(爲簡便起見被刪除的對象):

{ 
    "_embedded": { 
     "events": [ 
      {...}, 
      {...}, 
      {...}, 
      {...}, 
      {...} 
     ] 
    }, 
    "_links": { 
     "first": {...}, 
     "self": {...}, 
     "next": {...}, 
     "last": {...} 
    }, 
    "page": { 
     "size": 5, 
     "totalElements": 30, 
     "totalPages": 6, 
     "number": 0 
    } 
} 

你關心的對象是Event型的,那麼你應該執行類似的要求:

ResponseEntity<PagedResources<Event>> eventsResponse = restTemplate.exchange(uriBuilder.build(true).toUri(), 
       HttpMethod.GET, null, new ParameterizedTypeReference<PagedResources<Event>>() {}); 

如果您掌握如下資源:

PagedResources<Event> eventsResources = eventsResponse.getBody(); 

喲ü將能夠訪問該頁面的元數據(你在"page"部分獲得),鏈接("_links"部分)和內容:

Collection<Event> eventsCollection = eventsResources.getContent();