wake-up-neo.net

Wie verbrauchen Sie die Antwort der Seite <Entity> mit Spring RestTemplate?

Ich verwende Frühlingsdaten (mongoDb) und habe mein Repository:

public interface StoriesRepository extends PagingAndSortingRepository<Story, String> {}

Dann habe ich einen Controller:

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Page<StoryResponse>> getStories(Pageable pageable) {
    Page<StoryResponse> stories = storiesRepository.findAll(pageable).map(StoryResponseMapper::toStoryResponse);
    return ResponseEntity.ok(stories);
}

Alles funktioniert gut, aber ich kann meinen Endpunkt nicht mit der RestTemplate-Methode getForEntity verwenden:

def entity = restTemplate.getForEntity(getLocalhost("/story"), new TypeReference<Page<StoryResponse>>(){}.class)

Welche Klasse sollte ich anbieten, um meine Entity-Seite erfolgreich zu deserialisieren?

23
bgalek
new TypeReference<Page<StoryResponse>>() {}

Das Problem mit dieser Aussage ist, dass Jackson einen abstrakten Typ nicht instanziieren kann. Sie sollten Jackson die Informationen geben, wie Sie Page mit einem konkreten Typ instanziieren können. Sein konkreter Typ PageImpl hat jedoch keinen Standardkonstruktor oder @JsonCreators. Daher können Sie not den folgenden Code verwenden:

new TypeReference<PageImpl<StoryResponse>>() {}

Da Sie die erforderlichen Informationen nicht zur Page-Klasse hinzufügen können, ist es besser, eine benutzerdefinierte Implementierung für Page-Schnittstelle zu erstellen, die über einen No-Arg-Standardkonstruktor verfügt, wie in diesem answer . Verwenden Sie dann diese benutzerdefinierte Implementierung wie folgt:

new TypeReference<CustomPageImpl<StoryResponse>>() {}

Hier ist die benutzerdefinierte Implementierung, die aus der verknüpften Frage kopiert wurde:

public class CustomPageImpl<T> extends PageImpl<T> {
    private static final long serialVersionUID = 1L;
    private int number;
    private int size;
    private int totalPages;
    private int numberOfElements;
    private long totalElements;
    private boolean previousPage;
    private boolean firstPage;
    private boolean nextPage;
    private boolean lastPage;
    private List<T> content;
    private Sort sort;

    public CustomPageImpl() {
        super(new ArrayList<>());
    }

    @Override
    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    @Override
    public int getTotalPages() {
        return totalPages;
    }

    public void setTotalPages(int totalPages) {
        this.totalPages = totalPages;
    }

    @Override
    public int getNumberOfElements() {
        return numberOfElements;
    }

    public void setNumberOfElements(int numberOfElements) {
        this.numberOfElements = numberOfElements;
    }

    @Override
    public long getTotalElements() {
        return totalElements;
    }

    public void setTotalElements(long totalElements) {
        this.totalElements = totalElements;
    }

    public boolean isPreviousPage() {
        return previousPage;
    }

    public void setPreviousPage(boolean previousPage) {
        this.previousPage = previousPage;
    }

    public boolean isFirstPage() {
        return firstPage;
    }

    public void setFirstPage(boolean firstPage) {
        this.firstPage = firstPage;
    }

    public boolean isNextPage() {
        return nextPage;
    }

    public void setNextPage(boolean nextPage) {
        this.nextPage = nextPage;
    }

    public boolean isLastPage() {
        return lastPage;
    }

    public void setLastPage(boolean lastPage) {
        this.lastPage = lastPage;
    }

    @Override
    public List<T> getContent() {
        return content;
    }

    public void setContent(List<T> content) {
        this.content = content;
    }

    @Override
    public Sort getSort() {
        return sort;
    }

    public void setSort(Sort sort) {
        this.sort = sort;
    }

    public Page<T> pageImpl() {
        return new PageImpl<>(getContent(), new PageRequest(getNumber(),
                getSize(), getSort()), getTotalElements());
    }
}
29
Ali Dehghani

Ich weiß, dass dieser Thread ein wenig alt ist, aber hoffentlich wird jemand davon profitieren.

Die Antwort von @ALi Dehghani ist gut, außer dass sie das implementiert, was PageImpl<T> bereits getan hat. Ich hielt das für ziemlich unnötig. Ich habe eine bessere Lösung gefunden, indem ich eine Klasse erstellt habe, die PageImpl<T> erweitert und einen @JsonCreator-Konstruktor angibt:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.company.model.HelperModel;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import Java.util.List;

public class HelperPage extends PageImpl<HelperModel> {

    @JsonCreator
    // Note: I don't need a sort, so I'm not including one here.
    // It shouldn't be too hard to add it in tho.
    public HelperPage(@JsonProperty("content") List<HelperModel> content,
                      @JsonProperty("number") int number,
                      @JsonProperty("size") int size,
                      @JsonProperty("totalElements") Long totalElements) {
        super(content, new PageRequest(number, size), totalElements);
    }
}

Dann:

HelperPage page = restTemplate.getForObject(url, HelperPage.class);

Dies ist das Gleiche wie das Erstellen einer CustomPageImpl<T>-Klasse, es ermöglicht uns jedoch, den gesamten Code zu nutzen, der sich bereits in PageImpl<T> befindet.

15
jtcotton63

Als "Pfadfinder" können Sie die exchange-Methode von RestTemplate verwenden. Statt ParameterizedTypeReference<Page<StoryResponse>>() zu übergeben, sollten Sie ParameterizedTypeReference<PagedResources<StoryResponse>>() übergeben. Wenn Sie die Antwort erhalten, können Sie den Inhalt abrufen - Collection<StoryResponse>.

Der Code sollte so aussehen:

ResponseEntity<PagedResources<StoryResponse>> response = restTemplate.exchange(getLocalhost("/story"),
        HttpMethod.GET, null, new ParameterizedTypeReference<PagedResources<StoryResponse>>() {});
PagedResources<StoryResponse> storiesResources = response.getBody();
Collection<StoryResponse> stories = storiesResources.getContent();

Neben dem Inhalt enthält storiesResources auch Seitenmetadaten und Links.

Eine ausführlichere Erklärung finden Sie hier: https://stackoverflow.com/a/46847429/8805916

6
Vladimir Mitev

Wenn Sie sich diesen Thread ansehen, versuchen Sie es mit dieser Antwort https://stackoverflow.com/a/44895867/8268335

Sie werden das 2. Problem treffen:

Can not construct instance of org.springframework.data.domain.Pageable

Dann finde ich von hier aus die perfekte Lösung: https://stackoverflow.com/a/42002709/8268335

Ich erstelle die Klasse RestPageImpl aus der obigen Antwort und löste das Problem.

0
Terrence Wei

Ich kann nur die Spring Library auf 1. * herunterstufen und nicht 2. * .__ verwenden. Ich musste meinen eigenen Code für die Page erstellen, der PageImpl nicht erweitert

0
pama