我想构建一个可以处理多个可选排序查询的Spring控制器。根据spring.io规范,这些查询应该按照以下格式进行格式化。
&sort=name,desc&sort=code,desc
如EduardoFernandes所讨论的
我知道可以使用一个实例的排序值和单独给出方向来完成,如Gregg所述,但这与Spring规范不符合,也无法处理多个排序值。
我不确定如何将多个按Spring规范格式的查询转换为Sort,然后将其传递给我的PageRequest,再传递给我的存储库。此外,如果需要使用默认值来实现可选项,最好能够使用基于注解的配置,如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的Sort参数。根据Ralph的说法,我应该能够使用类似下面的方法从一个参数中获取多个值,但是我不知道如何将其传递给Sort。
我知道Sort可以接受多个参数,但只能有一个排序方向。当然,我希望它们是可选的。
@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自动将单个排序参数解析为字符串而不是String[]。
@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;
}
}
Pageable
的唯一方法不是使用PageRequest
吗?据我所知,没有超过一个排序的构造函数?(Pageable) - Rinus van Heerden@RequestParam(value = "sort", defaultValue = "name,ASC", required = false) List<String> sortBy
中的数组。 - Rinus van HeerdenSort allSorts = Sort.by( sortBy.stream() .map(sort -> sort.split(",", 2)) .map(array -> new Sort.Order(replaceOrderStringThroughDirection(array[0]),array[1]).ignoreCase() ).collect(Collectors.toList()) );
- Rinus van Heerden