Как вернуть ответы в стиле @RepositoryRestResource из @RestController - PullRequest
0 голосов
/ 05 июля 2018

Использование @RepositoryRestResource генерирует пути и внедряет все необходимые ссылки HATEOAS для REST API, но когда я возвращаю те же результаты из репозитория с использованием контроллера, структура JSON отличается и ссылок HATEOAS нет.

Как бы я мог вернуть ту же структуру JSON из контроллера, что и пути, сгенерированные RepositoryRestResource?

// /accounts (RepositoryRestResource JSON structure)
{
    _embedded: {
        accounts: []
    },
    _links: {
        first: {},
        self: {},
        next: {},
        last: {},
        profile: {},
        search: {}
    },
    page: {
    size: 20,
    totalElements: 35,
    totalPages: 2,
    number: 0
    }
}

// /my-accounts (RestController JSON structure)
{
    content: [ ... ], // accounts
    pageable: {},
    totalPages: 1,
    totalElements: 2,
    last: true,
    size: 20,
    number: 0,
    sort: {},
    numberOfElements: 2,
    first: true
}

REST репозиторий:

@RepositoryRestResource(collectionResourceRel = "accounts", path = "accounts", itemResourceRel = "account")
public interface AccountRepository extends PagingAndSortingRepository<Account, Long> {

    @RestResource(path = "owner", rel = "owner")
    Page<Account> findByOwner(@Param("username") String owner,Pageable p);
}

Контроллер REST:

@RestController
public class AccountController {

    private AccountRepository repo;

    @Autowired
    public AccountController(AccountRepository repo) {
        this.repo = repo;
    }

    @RequestMapping(
        path = "/my-accounts",
        method = RequestMethod.GET,
        produces = "application/hal+json")
    public ResponseEntity<Page<Account>> getStatus(
        @RequestParam(value = "page", defaultValue = "0", required = false) int page,
        @RequestParam(value = "size", defaultValue = "20", required = false) int size,
        Authentication authentication) {

        String username =  authentication.getName();

        Page<Account> accounts = repo.findByOwner(username, PageRequest.of(page, size));

        return ResponseEntity.ok(accounts);
    }
}

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

По сути, Spring Data REST - это просто стандартная реализация стандартного кода (например, контроллеров), который люди обычно пишут, предоставляя репозитории Spring Data через REST и используя Spring HATEOAS, то есть пытаясь воспроизвести точно такой же эффект с вашим рукописным контроллером. означает просто написать весь Spring Data REST самостоятельно, так что это плохая идея. К счастью, некоторые части легко воспроизвести.

Если вы говорите только о добавлении ссылок на пейджинг к выходу вашего контроллера (а не , реализующий другие вещи, такие как контроллер поиска, на который есть ссылка в вашем примере вывода контроллера Spring Data REST), вы можете взять Посмотрите на , как Spring Data REST делает это . Он использует PagedResourcesAssembler Spring Data, который принимает Page и создает ресурс HATEOAS с необходимыми ссылками навигации.

Итак, чтобы добавить ссылки подкачки, вы должны внедрить экземпляр PagedResourcesAssembler в свой контроллер и использовать его:

public ResponseEntity<PagedResources> getStatus(
    @RequestParam(value = "page", defaultValue = "0", required = false) int page,
    @RequestParam(value = "size", defaultValue = "20", required = false) int size,
    Authentication authentication,
    PagedResourcesAssembler assembler) {

    String username =  authentication.getName();

    Page<Account> accounts = repo.findByOwner(username, PageRequest.of(page, size));

    return ResponseEntity.ok(assembler.toResource(accounts));
}
0 голосов
/ 05 июля 2018

Не уверен, но это может сработать:

return ResponseEntity.ok(new org.springframework.hateoas.Resource<>(accounts));

Если нет, то вы можете заключить учетные записи в класс, который расширяет ResourceSupport. Так что просто создайте некоторый класс AccountSupport extends ResourceSupport и добавьте туда необходимые ссылки. У него много полезных методов, таких как

add(linkTo(AccountController.class).withSelfRel());

или для ссылок на отдельные учетные записи:

add(linkTo(AccountController.class).slash(idOfYourAccountInstance).withSelfRel())
...