【问题标题】:Multiple Sort Optional query - Spring REST Controller configuration with Pagination多重排序可选查询 - 带有分页的 Spring REST 控制器配置
【发布时间】:2019-07-13 10:26:33
【问题描述】:

我想构建一个可以处理多个可选排序查询的弹簧控制器。根据spring.io 规范,这些查询应该这样格式化

&sort=name,desc&sort=code,desc

正如EduardoFernandes所讨论的那样

我知道这可以通过一个带有要排序的值的排序实例来完成,并且方向按照 Gregg 单独给出,但这与 Spring 规范或处理多个排序值不匹配。

我不确定如何将 spring 规范格式的多个查询转换为我可以传递给我的 PageRequest 然后传递到我的存储库的排序。此外,我希望能够使这些成为可选的,如果可能的话,如果我可以使用基于@Anotation 的配置,如果按照Rasheed Amir(@SortDefault)需要默认值来实现这一点,那就太好了

这是我正在使用的基础知识..

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Subject {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String code; 
...

存储库

public interface SubjectRepository extends JpaRepository<Subject, Long> {
}

服务

@Override
public Page<SubjectDTO> listSubjectsPageble(PageRequest pageableRequest) {
    return subjectRepository.findAll(pageableRequest)
            .map(subjectMapper::subjectToSubjectDTO);
}

控制器

@GetMapping
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('LECTURER')")
public Page<SubjectDTO> getSubjects(
        @RequestParam("page") int page,
        @RequestParam("size") int size,
        @RequestParam("sort") String sort

) {

    return subjectService.listSubjectsPageble(PageRequest.of(page, size, new Sort(sort)));
}

因此,在控制器中,我根本不知道如何处理\填充 RequestParam 中的排序,根据Ralph,我应该能够使用类似下面的内容从一个参数中获取多个值,但我不知道如何将其传递给排序。

我知道一个排序可以接受多个参数,但只能接受一个排序方向。然后是粗略的,我想让它们成为可选的。

@RequestParam MultiValueMap<String, String> params

请帮忙,我还是个菜鸟 :) 谢谢

编辑

感谢Dullimeister 的帖子,我解决了一些问题,但这种方法感觉有点混乱,仍然无法处理多个排序参数。有谁知道更好的方法或者这是要走的路吗?

@GetMapping
    @ResponseStatus(HttpStatus.OK)
    @PreAuthorize("hasRole('LECTURER')")
    public Page<SubjectDTO> getSubjects(
            @RequestParam(value = "page", defaultValue = "0", required = false) int page,
            @RequestParam(value = "size", defaultValue = "10", required = false) int size,
            @RequestParam(value = "sort", defaultValue = "name,ASC", required = false) String sortBy

    ) {
        String[] sort = sortBy.split(",");
        String evalSort = sort[0];
        String sortDirection = sort[1];
        Sort.Direction evalDirection = replaceOrderStringThroughDirection(sortDirection);
        Sort sortOrderIgnoreCase = Sort.by(new Sort.Order(evalDirection,evalSort).ignoreCase());

        return subjectService.listSubjectsPageble(PageRequest.of(page, size, sortOrderIgnoreCase));
    }

    private Sort.Direction replaceOrderStringThroughDirection(String sortDirection) {
        if (sortDirection.equalsIgnoreCase("DESC")){
            return Sort.Direction.DESC;
        } else {
            return Sort.Direction.ASC;
        }
    }

最终解决方案 谢谢大家,这就是我最终的结果。不确定它是否是完美的方法,但它有效:) 最后我不得不用分号替换逗号,因为 FormattingConversionService 自动将单个排序参数解析为字符串而不是 Sting[]

@GetMapping
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('LECTURER')")
public Page<SubjectDTO> getSubjects(
        @RequestParam(value = "page", defaultValue = "0", required = false) int page,
        @RequestParam(value = "size", defaultValue = "10", required = false) int size,
        @RequestParam(value = "sort", defaultValue = "name;ASC", required = false) String[] sortBy

Sort allSorts = Sort.by(
        Arrays.stream(sortBy)
                .map(sort -> sort.split(";", 2))
                .map(array ->
                        new Sort.Order(replaceOrderStringThroughDirection(array[1]),array[0]).ignoreCase()
                ).collect(Collectors.toList())
);
return subjectService.listSubjectsPageble(PageRequest.of(page, size, allSorts));

private Sort.Direction replaceOrderStringThroughDirection(String sortDirection) {
    if (sortDirection.equalsIgnoreCase("DESC")){
        return Sort.Direction.DESC;
    } else {
        return Sort.Direction.ASC;
    }

【问题讨论】:

    标签: java spring rest jpa pagination


    【解决方案1】:

    为什么不在控制器中使用 Pageable

    Pageable 可以处理许多排序查询,每个查询都将存储在订单列表中。 此外,不需要任何可分页参数。当您不在 url 中传递它们时,pageable 将包含默认值(page = 0,size = 20)。您可以使用 @PageableDefault 注解更改默认值。

    GET .../test?sort=name,desc&sort=code,desc

    【讨论】:

    • 感谢您的回复。实现 Pageable 的唯一方法不是使用 PageRequest 吗?据我所知,存在不止一种类型的构造函数? (Pageable)
    • 是的,pageable 总是只包含一种排序,但是在那种排序中你可以有很多订单。
    • 好的,谢谢,现在的一个问题是,当我尝试从 @RequestParam 中提取多个排序字符串时,我希望它成为一个集合以便对其进行流式传输。然而,格式 $sort="id,asc" 被它的逗号分割成数组中的单独行,即@RequestParam(value = "sort", defaultValue = "name,ASC", required = false) List&lt;String&gt; sortBy
    • 我想在这里流式传输以构建所有“订单”,例如Sort allSorts = Sort.by( sortBy.stream() .map(sort -&gt; sort.split(",", 2)) .map(array -&gt; new Sort.Order(replaceOrderStringThroughDirection(array[0]),array[1]).ignoreCase() ).collect(Collectors.toList()) );
    • 但是 sortBy 给出的是 sortBy0='"id" 和 sortBy1="ASC" 而不是 sortBy0= "id,asc"
    猜你喜欢
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    相关资源
    最近更新 更多