Comment consommer la réponse de la Page à L'aide de Spring RestTemplate

j'utilise les données du printemps (mongoDb) et j'ai mon dépôt:

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

Alors j'ai un contrôleur:

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

Tout fonctionne bien, mais je ne peux pas consommer de mon point de terminaison à l'aide de RestTemplate getForEntity méthode:

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

quelle classe dois-je fournir pour réussir à desérialiser ma Page d'entités?

21
demandé sur bgalek 2015-12-05 03:07:13

6 réponses

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

le problème avec cette affirmation est que Jackson ne peut pas instancier un type abstrait. Vous devriez donner Jackson l'information sur la façon d'instancier Page avec un type de béton. Mais son type de béton, PageImpl, n'a pas de constructeur par défaut ou de tout @JsonCreator s d'ailleurs, donc vous pouvez utilisez le code suivant:

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

Puisque vous ne pouvez pas ajouter les informations requises à l' Page classe, Il est préférable de créer une implémentation personnalisée Page interface qui a un constructeur par défaut no-arg, comme dans ce réponse. Puis utilisez cette implémentation personnalisée dans la référence de type, comme suit:

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

Voici l'implémentation personnalisée, copiée à partir de la question liée:

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());
    }
}
26
répondu Ali Dehghani 2017-05-23 12:18:29

je sais que ce fil est un peu vieux, mais j'espère que quelqu'un en bénéficiera.

la réponse de@Ali Dehghani est bonne, sauf qu'elle ré-implante quoi PageImpl<T> l'a déjà fait. J'ai considéré que c'était plutôt inutile. J'ai trouvé une meilleure solution en créant une classe qui s'étend PageImpl<T> et spécifie un @JsonCreator constructeur:

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);
    }
}

Puis:

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

c'est la même chose que de créer un CustomPageImpl<T> classe mais qui nous permet de profiter de tous les code qui est déjà en PageImpl<T>.

9
répondu jtcotton63 2017-07-04 01:58:21

comme "pathfinder" mentionné, vous pouvez utiliser exchange méthode RestTemplate. Cependant, au lieu de passer ParameterizedTypeReference<Page<StoryResponse>>() vous devez passer ParameterizedTypeReference<PagedResources<StoryResponse>>(). Lorsque vous obtenez la réponse, vous pouvez extraire le contenu Collection<StoryResponse>.

Le code devrait ressembler à ceci:

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();

mis à part le contenu storiesResources contient aussi des métadonnées de page et des liens.

plus de l'étape-par-étape des explications est disponible ici: https://stackoverflow.com/a/46847429/8805916

6
répondu Vladimir Mitev 2017-10-20 12:16:43

Je ne peux que faire en sorte que ça marche en dégradant la bibliothèque de printemps à 1.* et ne pas utiliser 2.* J'ai dû créer mon propre code pour la Page qui ne s'étend pas PageImpl

0
répondu pama 2018-09-18 10:16:48

Vous pouvez probablement utiliser la méthode d'échange de restTemplate et obtenir le corps..

Cochez la réponse suivante https://stackoverflow.com/a/31947188/3800576. Cela peut vous aider

-1
répondu pathfinder 2017-05-23 11:47:29

Vous pouvez essayer d'ajouter l'annotation @Responsabilebody:

@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Page<StoryResponse>> getStories(@RequestBody Pageable pageable) {
    Page<StoryResponse> stories = storiesRepository.findAll(pageable).map(StoryResponseMapper::toStoryResponse);
    return ResponseEntity.ok(stories);
}
-5
répondu sunny 2016-02-09 17:19:13