如何使用Spring以一种宁静的方式过滤数据?

2022-09-01 23:26:38

正如标题所说。

我基本上很想做这样的请求

/api/todos/?completed=eq.true&created_at=lt.1486462109399

有没有准备好实现这样的目标?类似于Page/Pageable机制的东西会很棒。spring way

如果没有,我想我可以使用Hibernate Criteria Queries和Arspace Re-solvers来实现它。基本上允许我编写我的控制器,如

 @GetMapping
 public ResponseEntity<Page<TodoDTO>> listAll(Criteria criteria, Pageable pageable) 
 {
        Page<Todo> todos = todoService.listAll(criteria, pageable)
        ...
 }

自定义参数解析器将负责将查询字符串转换为条件。还不太确定如何在服务中处理它,但这就是我尝试实现它的方向。

这会是一个好方法吗?有什么建议吗?(所有这些都假设还没有现成的机制)。

非常感谢您的帮助。


答案 1

构建流畅查询 API 的另一个选项是使用 RSQL 解析器。RSQL是一种查询语言,用于对RESTful API中的条目进行参数化过滤。按照本文操作,您的 API 将能够处理如下 URL:

http://localhost:8080/users?search=firstName==jo*;age<25

样品控制器:

@RestController
@RequestMapping(value = "/users")
public class UserController {

    @Autowired
    private UserRepository repo;

    @GetMapping
    public List<User> findAllByRsql(@RequestParam(value = "search") String search) {
        Node rootNode = new RSQLParser().parse(search);
        Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
        return repo.findAll(spec);
    }

}

Gradle dependency:

// https://mvnrepository.com/artifact/cz.jirutka.rsql/rsql-parser
implementation("cz.jirutka.rsql:rsql-parser:2.1.0")

库作者的建议:

我建议使用单独的URI查询参数进行排序,例如,不要将其与RSQL表达式混合。这同样适用于分页;我建议使用名为 和 的 URI 参数。?query=name==Flynn&sortBy=namelimitoffset


答案 2

您可以使用Spring Data JPA和Prospecs来构建搜索/过滤REST API。下面是生成的 API 能够处理的测试 URL 示例:

http://localhost:8080/users?search=lastName:doe,age>25

和示例控制器:

@RestController
@RequestMapping(value = "/users")
public class UserController {

    @Autowired
    private UserRepository repo;

    @GetMapping
    public List<User> search(@RequestParam(value = "search") String search) {
        UserSpecificationsBuilder builder = new UserSpecificationsBuilder();
        Pattern pattern = Pattern.compile("(\w+?)(:|<|>)(\w+?),");
        Matcher matcher = pattern.matcher(search + ",");
        while (matcher.find()) {
            builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
        }

        Specification<User> spec = builder.build();
        return repo.findAll(spec);
    }
}

推荐