2017-09-06 3 views
1

私のリポジトリのカスタムコントローラを定義しました。例えば、一つはこのSpring RepositoryRestControllerで_linksを取得

@RequestMapping(method = RequestMethod.GET, value = "/myEntities") 
public ResponseEntity<?> get() { 
    ...TO SOME STUFF 
    MyEntity myEntity= myEntityRepository.findById(1); 
    return ResponseEntity.ok(new Resource<>(myEntity)); 
} 

これは私がエンティティへのhrefを取得することができます_linksセクションを備えてJSON形式のデータを返すように見えます。 すべてのリソースであるエンティティの配列を返す場合、私は立ち往生します。

1.

@RequestMapping(method = RequestMethod.GET, value = "/myEntities") 
public ResponseEntity<?> get() { 
    ...TO SOME STUFF 
    List<MyEntity> myEntityList= myEntityRepository.findAll(1); 
    return ResponseEntity.ok(new Resources<>(myEntityList)); 
} 

2.

@RequestMapping(method = RequestMethod.GET, value = "/myEntities") 
public ResponseEntity<?> get() { 
    ...TO SOME STUFF 
    List<MyEntity> myEntityList= myEntityRepository.findAll(); 
    List<Resource<MyEntity>> resources = new ArrayList<>(); 
    myEntityList.forEach(me -> { 
     resources.add(new Resource<>(me)); 
    }) 
    return ResponseEntity.ok(resources); 
} 

オプション1と2はに_linksを追加しないでください:私がこれまで試してみました何

結果と私はなぜ理解していない。私はそれをたくさんのグーグルと手動でリンクを追加することができますが、これははるかに明確な方法と思われる。誰でも理解できますか、私は間違っていますか?

答えて

0

Resourcesコンストラクタは、リンクの集合と同じではない埋め込みコンテンツのコレクションを受け入れます。手動でリンクを追加する必要があります。

Resources resources = new Resources(); 
resources.add(myEntityRepository 
    .findAll() 
    .stream() 
    .map(entry -> convertToLink(entry) 
    .collect(Collectors.toList())); 
return ResponseEntity.ok(resources); 

ここでは、HAL準拠の形式で埋め込みコンテンツとページ番号を含む例を示します。

import static java.util.Objects.*; 
import static java.util.Optional.*; 
import static org.elasticsearch.index.query.QueryBuilders.*; 
import static org.springframework.hateoas.MediaTypes.*; 
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.*; 
import static org.springframework.http.HttpStatus.*; 
import static org.springframework.http.MediaType.*; 
import static org.springframework.web.bind.annotation.RequestMethod.*; 

import java.util.ArrayList; 

import javax.inject.Inject; 
import javax.validation.constraints.Min; 
import javax.validation.constraints.NotNull; 

import org.elasticsearch.index.query.QueryBuilder; 
import org.springframework.data.domain.Page; 
import org.springframework.data.domain.PageRequest; 
import org.springframework.data.domain.Sort; 
import org.springframework.data.elasticsearch.core.ElasticsearchOperations; 
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; 
import org.springframework.hateoas.Link; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.RestController; 

import com.codahale.metrics.annotation.Timed; 

@RestController 
@RequestMapping("/catalog/users") 
public class UserResource { 

    private final @NotNull UserLocator locator; 
    private final @NotNull ElasticsearchOperations elasticsearchTemplate; 

    @Inject 
    public UserResource(
     final @NotNull UserLocator locator, 
     final @NotNull ElasticsearchOperations elasticsearchTemplate 
    ) { 
     this.locator = requireNonNull(locator, "locator cannot be null"); 
     this.elasticsearchTemplate = requireNonNull(elasticsearchTemplate, "elasticsearchTemplate cannot be null"); 
    } 

    /** 
    * GET /users : get all the users. 
    * 
    * @return the ResponseEntity with status 200 (OK) and the list of users in body 
    */ 
    @Timed 
    @RequestMapping(method = GET, produces = { HAL_JSON_VALUE, APPLICATION_JSON_VALUE }) 
    public ResponseEntity<Representations<User>> allUsers(
     @RequestParam(name = "page", required = false, defaultValue = "0") @Min(0) int page, 
     @RequestParam(name = "size", required = false, defaultValue = "25") @Min(1) int size, 
     @RequestParam(name = "like", required = false) String like 
    ) { 
     final PageRequest pageRequest = new PageRequest(page, size, Sort.Direction.ASC, "surname.raw", "givenName.raw"); 
     final Page<User> entries = elasticsearchTemplate.queryForPage(
      new NativeSearchQueryBuilder() 
       .withQuery(startingWith(like)) 
       .withPageable(pageRequest) 
       .build(), 
      User.class 
     ); 

     final ArrayList<Link> links = new ArrayList<>(); 
     links.add(linkTo(UserResource.class).withSelfRel()); 

     if (!entries.isFirst()) { 
      links.add(linkTo(methodOn(UserResource.class).allUsers(0, size, like)).withRel("first")); 
     } 
     if (!entries.isLast()) { 
      links.add(linkTo(methodOn(UserResource.class).allUsers(entries.getTotalPages() - 1, size, like)).withRel("last")); 
     } 
     if (entries.hasNext()) { 
      links.add(linkTo(methodOn(UserResource.class).allUsers(entries.nextPageable().getPageNumber(), size, like)).withRel("next")); 
     } 
     if (entries.hasPrevious()) { 
      links.add(linkTo(methodOn(UserResource.class).allUsers(entries.previousPageable().getPageNumber(), size, like)).withRel("prev")); 
     } 

     final Representations<User> resourceList = new Representations<>(entries, Representations.extractMetadata(entries), links); 
     return ResponseEntity.ok(resourceList); 
    } 

    private QueryBuilder startingWith(String like) { 
     return isNull(like) ? null : matchPhrasePrefixQuery("_all", like); 
    } 

    /** 
    * GET /users/:identifier : get the "identifier" user. 
    * 
    * @param identifier the identifier of the role to retrieve 
    * @return the ResponseEntity with status 200 (OK) and with body the role, or with status 404 (Not Found) or with 410 (Gone) 
    */ 
    @Timed 
    @RequestMapping(value = "/{identifier}", method = GET, produces = APPLICATION_JSON_VALUE) 
    public ResponseEntity<UserRepresentation> aUser(
     @PathVariable("identifier") @NotNull String identifier 
    ) { 
     return ofNullable(this.locator.findOne(identifier)) 
      .map(user -> toRepresentation(user)) 
      .map(ResponseEntity::ok) 
      .orElse(notFound()) 
      ; 
    } 

    private @NotNull UserRepresentation toRepresentation(final @NotNull User role) { 
     final String id = role.getIdentifier(); 
     final Link self = linkTo(methodOn(UserResource.class).aUser(id)).withSelfRel().expand(id); 
     final Link collection = linkTo(UserResource.class).withRel("collection"); 
     return new UserRepresentation(role, self, collection); 
    } 

    protected final @NotNull <U> ResponseEntity<U> notFound() { 
     return new ResponseEntity<>(NOT_FOUND); 
    } 

} 

import java.util.Optional; 

import org.springframework.hateoas.Link; 
import org.springframework.hateoas.core.Relation; 

@Relation(value = "item", collectionRelation = "items") 
public class UserRepresentation extends Representation<User> { 

    public UserRepresentation(User content, Iterable<Optional<Link>> links) { 
     super(content, links); 
    } 

    public UserRepresentation(User content, Link... links) { 
     super(content, links); 
    } 

    @SafeVarargs 
    public UserRepresentation(User content, Optional<Link>... links) { 
     super(content, links); 
    } 

    public UserRepresentation(User content) { 
     super(content); 
    } 

} 

import static java.util.Arrays.*; 
import static java.util.Collections.*; 
import static java.util.Objects.*; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.Optional; 

import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 

import org.springframework.hateoas.Link; 
import org.springframework.hateoas.Resource; 
import org.springframework.hateoas.ResourceSupport; 

import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonInclude.Include; 
import com.fasterxml.jackson.annotation.JsonProperty; 

public class Representation<T> extends Resource<T> { 
    private final Map<String, ResourceSupport> embedded = new HashMap<>(); 

    public Representation(final @NotNull T content) { 
     super(content, emptyList()); 
    } 

    public Representation(final @NotNull T content, final @NotNull Link... links) { 
     super(content, links); 
    } 

    @SafeVarargs 
    public Representation(final @NotNull T content, final @NotNull Optional<Link>... links) { 
     this(content, (Iterable<Optional<Link>>) asList(links)); 
    } 

    public Representation(final @NotNull T content, final @NotNull Iterable<Optional<Link>> links) { 
     super(content, emptyList()); 
     asStream(links).forEach(this::add); 
    } 

    public void add(final @NotNull Optional<Link> link) { 
     if (null != link && link.isPresent()) super.add(link.get()); 
    } 

    @JsonProperty("_embedded") 
    @JsonInclude(Include.NON_EMPTY) 
    public final @NotNull Map<String, ResourceSupport> getEmbedded() { 
     return this.embedded; 
    } 

    /** 
    * @param rel must not be {@literal null} or empty. 
    * @param resource the resource to embed 
    */ 
    public final void embed(final @NotNull @Size(min=1) String rel, final ResourceSupport resource) { 
     requireNonNull(rel, "rel cannot be null"); 
     if (rel.trim().isEmpty()) { 
      throw new IllegalArgumentException("rel cannot be empty"); 
     } 
     if (null != resource) { 
      this.embedded.put(rel, resource); 
     } 
    } 

} 

import javax.validation.constraints.NotNull; 

import org.springframework.data.domain.Page; 
import org.springframework.hateoas.Link; 
import org.springframework.hateoas.Resources; 
import org.springframework.hateoas.PagedResources.PageMetadata; 
import org.springframework.hateoas.core.Relation; 

import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.annotation.JsonUnwrapped; 

@Relation(collectionRelation = "items") 
public class Representations<T> extends Resources<T> { 

    @JsonUnwrapped 
    @JsonInclude(JsonInclude.Include.NON_NULL) 
    private final PageMetadata metadata; 

    public Representations(Iterable<T> content) { 
     super(content); 
     this.metadata = null; 
    } 

    public Representations(Iterable<T> content, PageMetadata metadata) { 
     super(content); 
     this.metadata = metadata; 
    } 

    public Representations(Iterable<T> content, Iterable<Link> links) { 
     super(content, links); 
     this.metadata = null; 
    } 

    public Representations(Iterable<T> content, PageMetadata metadata, Iterable<Link> links) { 
     super(content, links); 
     this.metadata = metadata; 
    } 

    public Representations(Iterable<T> content, Link... links) { 
     super(content, links); 
     this.metadata = null; 
    } 

    public Representations(Iterable<T> content, PageMetadata metadata, Link... links) { 
     super(content, links); 
     this.metadata = metadata; 
    } 

    /** 
    * Returns the pagination metadata. 
    * 
    * @return the metadata 
    */ 
    @JsonProperty("page") 
    public PageMetadata getMetadata() { 
     return metadata; 
    } 

    public static <U> PageMetadata extractMetadata(final @NotNull Page<U> page) { 
     return new PageMetadata(page.getSize(), page.getNumber(), page.getTotalElements(), page.getTotalPages()); 
    } 
} 
-1

は "adding association links to spring data rest custom exposed method" と類似の質問のための "Enable HAL serialization in Spring Boot for custom controller method" の答えがあります。似たような状況を解決するために、私はそれらの答えと少し違ったことを試してみました。うまくいきました。私はあなたの問題を解決してほしい。

@PostMapping(value = "/myEntities/searchWithParams" 
     , consumes = MediaType.APPLICATION_JSON_VALUE 
     , produces = MediaType.APPLICATION_JSON_VALUE) 
public ResponseEntity<?> searchWithParams(@RequestBody SearchParamsDtoClass params, PersistentEntityResourceAssembler assembler) 
{ 
    List<MyEntity> entities = myEntityService.searchWithParams(params); 
    List<PersistentEntityResource> resourcesList = new ArrayList<PersistentEntityResource>(); 

    for (MyEntity entity: entities) { 
     PersistentEntityResource resource = assembler.toResource(entity); 
     resourcesList.add(resource); 
    } 

    Resources<PersistentEntityResource> resources = new Resources(resourcesList); 

    return ResponseEntity.ok(resources); 
} 
+0

このリンクは質問に答えるかもしれないが、ここでは答えの重要な部分が含まれており、参照のためのリンクを提供した方がよい:

私が私の特定の状況を解決したのか、次の。リンクされたページが変更された場合、リンクのみの回答は無効になります。 - [レビューから](/レビュー/低品質の投稿/ 18963405) – Liam

+0

ここは@Liamです。 – FSAA

関連する問題