【问题标题】:Exposing a paginated search link and its arguments公开分页搜索链接及其参数
【发布时间】:2014-08-18 21:45:29
【问题描述】:

我正在使用最新的 Spring REST 和 HATEOAS 尝试公开指向搜索端点的链接。

这里是资源汇编器:

@Component
public class AdminResourceAssembler extends ResourceAssemblerSupport<Admin, AdminResource> {

    public AdminResourceAssembler() {
        super(AdminController.class, AdminResource.class);
    }

    public AdminResource toResource(Admin admin) {
        AdminResource adminResource = createResourceWithId(admin.getId(), admin);
        BeanUtils.copyProperties(admin, adminResource);
        adminResource.add(linkTo(AdminController.class).slash(admin.getId()).slash("module").withRel("module"));        
        return adminResource;
    }

}

这里是端点控制器:

@RequestMapping(value = UriMappingConstants.PATH_SEPARATOR + UriMappingConstants.SEARCH, method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<PagedResources<AdminResource>> search(@RequestParam(value = "searchTerm", required = true) String searchTerm, @PageableDefault Pageable pageable, PagedResourcesAssembler<Admin> pagedResourcesAssembler, UriComponentsBuilder builder) {
    HttpHeaders responseHeaders = new HttpHeaders();
    Pageable pageRequest = buildPageRequest(pageable.getPageNumber(), pageable.getPageSize());
    Page<Admin> searchedAdmins = adminService.search(searchTerm, pageRequest);
    responseHeaders.setLocation(builder.path(UriMappingConstants.PATH_SEPARATOR + UriMappingConstants.ADMINS + UriMappingConstants.PATH_SEPARATOR + "search").queryParam("searchTerm", searchTerm).queryParam("page", pageable.getPageNumber()).queryParam("size", pageable.getPageSize()).buildAndExpand(searchTerm).toUri());
    PagedResources<AdminResource> adminPagedResources = pagedResourcesAssembler.toResource(searchedAdmins, adminResourceAssembler);
    return new ResponseEntity<PagedResources<AdminResource>>(adminPagedResources, responseHeaders, HttpStatus.OK);
}

private Pageable buildPageRequest(int pageIndex, int pageSize) {
    Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC, "lastname"), new Sort.Order(Sort.Direction.ASC, "firstname"));
    return new PageRequest(pageIndex, pageSize, sort);
}

首先,我不确定是否应该调用 buildPageRequest 方法并简单地将原始 pageable 传递给搜索服务。

我有两个问题:

响应中发布的链接缺少 searchTerm 参数:

{"rel":"self","href":"http://localhost:8080/nitro-project-rest/admins/search{?page,size,sort}

我希望它是这样的:

{"rel":"self","href":"http://localhost:8080/nitro-project-rest/admins/search{?searchTerm,page,size,sort}

但同样,作为一个新手,我不确定。

并且控制器总是获取 10 个项目的第一页,忽略我在请求中提供的页码和大小参数:

curl -H "Accept:application/json" --user joethebouncer:mignet http://localhost:8080/nitro-project-rest/admins/search?searchTerm=irstna&page=3&size=5

我想我离解决方案不远了,但我什至不知道暴露的链接应该是什么样子。

任何方向都会很好:-)

编辑:添加信息

可分页配置:

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
    argumentResolvers.add(resolver);
    super.addArgumentResolvers(argumentResolvers);
}

该服务只是对存储库的一个包装:

public Page<Admin> search(String searchTerm, Pageable page) {
  return adminRepository.search(searchTerm, page);
}

这是一个接口:

@Query("SELECT a FROM Admin a WHERE LOWER(a.firstname) LIKE LOWER(CONCAT('%', :searchTerm, '%')) OR LOWER(a.lastname) LIKE LOWER(CONCAT('%', :searchTerm, '%')) OR LOWER(a.email) LIKE LOWER(CONCAT('%', :searchTerm, '%')) OR LOWER(a.login) LIKE LOWER(CONCAT('%', :searchTerm, '%')) ORDER BY a.lastname ASC, a.firstname ASC") public 

页面搜索(@Param("searchTerm") String searchTerm, Pageable page);

数据库是JPA前端的H2,控制台显示:

可以看到偏移量少了……

select admin0_.id as id1_1_, admin0_.version as version2_1_, admin0_.email as email3_1_, admin0_.firstname as firstnam4_1_, admin0_.lastname as lastname5_1_, admin0_.login as login6_1_, admin0_.password as password7_1_, admin0_.password_salt as password8_1_, admin0_.post_login_url as post_log9_1_ from admin admin0_ where lower(admin0_.firstname) like lower(('%'||'irstn'||'%')) order by admin0_.lastname ASC, admin0_.firstname ASC, admin0_.lastname asc, admin0_.firstname asc limit 10

亲切的问候,

斯蒂芬·艾伯特

【问题讨论】:

  • 你在使用@enableautoconfiguration 吗?
  • 不,从未听说过该注释。让我谷歌一下……
  • Stephane,我看到你在patrickgrimard.com/2014/05/16/… 解决了这个问题。您愿意分享您的解决方案吗?
  • @JohnDeverall 我在他博客的评论中分享了它。我必须承认那是一年前的事了,我对此失去了背景。你看过他的博客文章吗?它应该易于遵循和实施。

标签: rest hateoas spring-hateoas


【解决方案1】:

不知道 buildPageRequest 在做什么......但我敢打赌你不需要它,它是你的分页问题的根源

关于自我链接。 PagedResourceAssembler 创建了一个非常简单的默认程序...但是您可以构建一个更复杂的程序并将其作为 toResource 方法的第三个参数传入。因此,只需以多种方式中的任何一种方式构建您自己的链接。我建议如下:

  linkTo(methodOn(SomeController.class).search(searchTerm, pageable, null, null))

还有一点需要注意的是,self 链接永远不应该被模板化,所以这是 spring-hateoas 中的一个错误(实际上是一个依赖项),请参阅 https://jira.spring.io/browse/DATACMNS-515

【讨论】:

  • 我在源代码中包含了 buildPageRequest 方法。它只是构建页面请求排序顺序。
  • 您确定您的服务尊重可分页吗?
  • 我添加了一个linkTo:adminPagedResources.add(linkTo(methodOn(AdminController.class).search(searchTerm, pageable, pagedResourcesAssembler, builder)).withRel("search"));我可以在回复中看到:{"links":[{"rel":"next","href":"localhost:8080/nitro-project-rest/admins/…"},{"rel":"self","href":"@987654323 @{?page,size,sort}"},{"rel":"search","href":"localhost:8080/nitro-project-rest/admins/…"}],"content" 但生成的自链接不同。
  • 我的控制器端点忽略了页码和大小。它接收的参数是 pageable page: 0 和 size: 10 这是请求: curl -H "Accept:application/json" --user joethebouncer:mignet localhost:8080/nitro-project-rest/admins/…
  • 你不调用 add,你将它作为第三个参数传递给 toResource 你应该让 rel self
【解决方案2】:

我太傻了。我看不到 curl 需要在 url 周围加上双引号来允许多个参数。 curl -H "Accept:application/json" --user joethebouncer:mignet "localhost:8080/nitro-project-rest/admins/... 现在可以正常工作了。

【讨论】:

    猜你喜欢
    • 2016-12-10
    • 1970-01-01
    • 2015-10-27
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 2015-09-26
    • 2013-08-10
    相关资源
    最近更新 更多