Comment utiliser correctement PagedResourcesAssembler à partir de Données du Printemps?
Je suis en utilisant le Printemps 4.0.0.LIBÉRATION, le Printemps de Données Communes 1.7.0.M1, Printemps Hateoas 0.8.0.COMMUNIQUÉ de
Ma ressource est un simple POJO:
public class UserResource extends ResourceSupport { ... }
Ma ressource assembleur convertit les objets Utilisateur à UserResource objets:
@Component
public class UserResourceAssembler extends ResourceAssemblerSupport<User, UserResource> {
public UserResourceAssembler() {
super(UserController.class, UserResource.class);
}
@Override
public UserResource toResource(User entity) {
//map User to UserResource
}
}
À l'intérieur de mon UserController je veux récupérer Page<User>
de mon service, puis le convertir en PagedResources<UserResource>
à l'aide de PagedResourcesAssembler
, comme montré ici: https://stackoverflow.com/a/16794740/1321564
@RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(@PageableDefault Pageable p, PagedResourcesAssembler assembler) {
Page<User> u = service.get(p)
return assembler.toResource(u);
}
Ce n'appelle pas UserResourceAssembler
et simplement le contenu de User
sont retournés à la place de ma coutume UserResource
.
Retourner une seule ressource de travaux:
@Autowired
UserResourceAssembler assembler;
@RequestMapping(value="{id}", method=RequestMethod.GET)
UserResource getById(@PathVariable ObjectId id) throws NotFoundException {
return assembler.toResource(service.getById(id));
}
La PagedResourcesAssembler
en veut argument générique, mais je ne peux pas utiliser T toResource(T)
, parce que je ne veux pas convertir mes Page<User>
à PagedResources<User>
, en particulier parce que User
est un POJO et aucune Ressource.
La question est donc: Comment ça fonctionne?
EDIT:
Mon WebMvcConfigurationSupport:
@Configuration
@ComponentScan
@EnableHypermediaSupport
public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(pageableResolver());
argumentResolvers.add(sortResolver());
argumentResolvers.add(pagedResourcesAssemblerArgumentResolver());
}
@Bean
public HateoasPageableHandlerMethodArgumentResolver pageableResolver() {
return new HateoasPageableHandlerMethodArgumentResolver(sortResolver());
}
@Bean
public HateoasSortHandlerMethodArgumentResolver sortResolver() {
return new HateoasSortHandlerMethodArgumentResolver();
}
@Bean
public PagedResourcesAssembler<?> pagedResourcesAssembler() {
return new PagedResourcesAssembler<Object>(pageableResolver(), null);
}
@Bean
public PagedResourcesAssemblerArgumentResolver pagedResourcesAssemblerArgumentResolver() {
return new PagedResourcesAssemblerArgumentResolver(pageableResolver(), null);
}
/* ... */
}
SOLUTION:
@Autowired
UserResourceAssembler assembler;
@RequestMapping(value="", method=RequestMethod.GET)
PagedResources<UserResource> get(@PageableDefault Pageable p, PagedResourcesAssembler pagedAssembler) {
Page<User> u = service.get(p)
return pagedAssembler.toResource(u, assembler);
}
Vous devez vous connecter pour publier un commentaire.
Vous semblent déjà avoir trouvé la bonne façon de l'utiliser, mais je voudrais entrer dans certains détails ici un peu pour les autres à trouver. Je suis allé dans des détails semblables sur
PagedResourceAssembler
dans cette réponse.Modèles de représentation de l'
Printemps HATEOAS est livré avec une variété de classes de base pour les modèles de représentation qui font qu'il est facile de créer des représentations équipé avec des liens. Il existe trois types de classes sont fournis à l'extérieur de la boîte:
Resource
- un élément de ressource. Effectivement, pour envelopper autour de certains DTO ou de l'entité qui capture un unique élément et l'enrichit avec des liens.Resources
- une collection de ressources, qui peut être une collection de choses, mais, habituellement, sont une collection deResource
instances.PagedResources
- une extension deResources
que les captures supplémentaires de la pagination des informations comme le nombre total de pages etc.Toutes ces classes dérivent de
ResourceSupport
, qui est un conteneur pourLink
instances.Ressources assembleurs
Un
ResourceAssembler
est maintenant l'atténuation de la composante de convertir vos objets du domaine ou de l'Otd dans ces instances de ressources. L'important est ici, qu'il s' un objet source dans un objet cible.De sorte que le
PagedResourcesAssembler
va prendre un Printemps de DonnéesPage
instance et de la transformer en unPagedResources
exemple par l'évaluation de laPage
et de la création de la nécessairePageMetadata
ainsi que laprev
etnext
liens pour naviguer dans les pages. Par défaut - et c'est probablement la partie la plus intéressante ici - il utiliser une plaineSimplePagedResourceAssembler
(un à l'intérieur de la classe dePRA
) pour transformer les différents éléments de la page en imbriquéeResource
instances.Permettent de le personnaliser,
PRA
a d'autrestoResource(…)
des méthodes qui prennent un déléguéResourceAssembler
pour traiter les éléments individuels. Si vous vous retrouvez avec quelque chose comme ceci:Et le code client maintenant à la recherche de quelque chose comme ceci:
Outlook
De Printemps à venir des Données Communes de 1,7 RC1 (et le Printemps HATEOAS de 0,9 transitivement) le
prev
etnext
liens seront générés comme RFC6540 conforme URI modèles à exposer la pagination à la demande des paramètres configurés dans leHandlerMethodArgumentResolvers
pourPageable
etSort
.La configuration que vous avez indiqué ci-dessus peut être simplifiée par l'annotation de la config de classe avec
@EnableSpringDataWebSupport
qui vous permet de vous débarrasser de toutes les explicite bean déclarations.PagedResourcesAssembler
? Je ne peux l'utiliser comme matières premières de type. Il ditPagedResources<R> toResource(Page<T>, ResourceAssemblerSupport<T, R>)
. Eclipse n'accepte pas cette:PagedResources<UserResource> p = parAssembler.toResource(userPage, userResourceAssembler)
.PagedResourcesAssembler
dans la réponse ci-dessus. Si vous fournir une coutumeUserResourceAssembler
qui est unResourceAssembler<User, UserResource>
, vous avez besoin pour obtenir unPagedResourcesAssembler<User>
injecté de créer, à termePagedResources<UserResource>
. J'ai juste ajouté un de cas de test pour le code de base donnant un exemple de cela.PagedResourcesAssembler
prend une entité JPA et la@Controller
signature de la méthode prend unPagedResourcesAssembler<JPAEntity>
? Quand je pense au sujet de ma mise en œuvre, cela se sent comme une abstraction qui fuit. J'ai l'impression que l'abstraction serait plus cohérent siPagedResourcesAssembler
a pris un<Resource of JPAEntity>
. De cette façon, notre couche de persistance de la traite avec des entités JPA et notre service à la couche de cartes ceux<? extends ResourceSupport>
. Je ne s'attendent généralement pas des entités JPA pour être référencé au-dessus de la couche de service. Suis-je à l'aide de l'API de façon incorrecte?Resource
ni unResourceAssembler
classe, cela m'amène à penser que les DTS pourraient avoir un générique de mise en œuvre de ces classes. Est-il un moyen de l'utiliser?J'ai voulu convertir une liste de Ressources à la page. mais quand lui donnant PagedResourcesAssembler il était en train de manger les liens internes.
Cette obtiendrez votre Liste paginée.
Paginé de ressources Fournissant ResourceAssembler dire Paginé de ressources pour l'utiliser, ce qui n'est pas tout simplement du retour en arrière, comme c'est déjà d'une liste de ressources qui est transmis.
AUTRE FAÇON
Un autre moyen est d'utiliser la Gamme d'en-tête HTTP (lire la suite dans RFC 7233). Vous pouvez définir l'en-tête HTTP de cette façon:
Qui signifie, vous souhaitez obtenir des ressources de 20 à 41 (y compris). De cette façon permet consuments de l'API de recevoir exactement défini ressources.
C'est juste la façon alternative. La gamme est souvent utilisé avec d'autres unités (comme les octets etc.)
RECOMMANDÉ
Si vous voulez travailler avec la pagination et ont vraiment applicable API (hypermédia /HATEOAS inclus) alors je recommande d'ajouter une Page et PageSize à votre URL. Exemple:
Ensuite, vous pouvez lire ces données dans votre BaseApiController et de créer une certaine QueryFilter objet dans l'ensemble de vos demandes:
Votre api retourne quelques collection spéciale avec des informations sur le nombre d'éléments.
Votre modèle de classes peuvent hériter d'une classe avec la pagination de soutien:
PagedResourcesAssembler
. Modèle de classes ne doit jamais hériter de toutes les API de trucs....
ConcernantRange
: Pas recommandable à tous! L'URL générée n'est pas la quantité, mais la demande doit être. Cela signifie, que je peux appeler la même URL avec différentsRange
en-têtes et obtenir des résultats différents. --- Vous ne pouvez pas copier et coller l'URL et obtenir le même résultat, parce que vous allez toujours perdre laRange
de l'information.