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

Posted

技术标签:

【中文标题】如何使用 Spring 以一种宁静的方式过滤数据?【英文标题】:How do I filter data in a restful way using Spring? 【发布时间】:2017-06-24 13:57:01 【问题描述】:

正如标题所说。

我基本上很乐意做类似的请求

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

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

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

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

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

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

非常感谢您的帮助。

【问题讨论】:

上次我遇到了同样的问题,我找不到仅弹簧的解决方案。但是,您可以通过使用 Fiql/rsql 来检查如何实现这一点,这是一个很好的 [博客](baeldung.com/rest-api-search-language-rsql-fiql)。 你问这个问题已经一年了,我不知道你在哪里,但这应该能回答你的问题:baeldung.com/…你也可以检查这个问题:***.com/questions/20280708/… 【参考方案1】:

作为 RQSL 的一个很好的替代方案,您可以使用以下库:https://github.com/turkraft/spring-filter

它将让您运行搜索查询,例如:

/search?filter= 平均(收视率)> 4.5 brand.name in (“奥迪”、“路虎”)(年> 2018 公里 50000) 和颜色 : '白色' 意外是空的

正如您在示例中看到的,它支持函数、搜索嵌套字段、嵌套逻辑、枚举、字符串、数字、布尔值、日期......

非常简单的用法:

@GetMapping(value = "/search")
public Page<Entity> search(@Filter Specification<Entity> spec, Pageable page) 
  return repo.findAll(spec, page);

无需配置任何东西,只需导入依赖即可:

<dependency>
    <groupId>com.turkraft</groupId>
    <artifactId>spring-filter</artifactId>
    <version>1.0.5</version>
</dependency>

还有使用 MongoDB 的示例。

【讨论】:

【参考方案2】:

您可能还想尝试 Spring Search: https://github.com/sipios/spring-search

示例:/cars?search=creationyear:2018 AND price

【讨论】:

【参考方案3】:

构建流畅查询 API 的另一个选择是使用 RSQL 解析器。 RSQL 是一种查询语言,用于对 RESTful API 中的条目进行参数化过滤。关注this article,您的 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);
    


【讨论】:

是否可以同时与分页结合使用? @Rekin 是的。建议使用单独的参数limitoffset 进行分页。来源:rsql-parser #9【参考方案4】:

你可以建立一个Search/Filter REST API using Spring Data JPA and Specifications。 以下是生成的 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);
    

【讨论】:

这是正确答案。 leventunver 在对 OP 问题的评论中也提到了。 什么是 UserSpecificationBuilder ? @Nimo1981 在我的回答中,我只嵌入了一个简洁的控制器示例来展示建议的解决方案。要查找有关该解决方案的更多详细信息,请点击我的答案中的链接并阅读 Baeldung 的文章。或者查看 GitHub 上的完整实现 -> github.com/eugenp/tutorials/tree/master/…(如果您要查找的唯一内容,请搜索 UserSpecificationsBuilder 关键字)。 @naXa 评论中的 github 链接已失效 @chriswillow 在 Baeldung 的文章末尾有一个新链接 -> github.com/eugenp/tutorials/tree/master/spring-web-modules/…

以上是关于如何使用 Spring 以一种宁静的方式过滤数据?的主要内容,如果未能解决你的问题,请参考以下文章

Spring概述

使用 Ajax 以一种形式上传数据和文件?

使用 Ajax 以一种形式上传数据和文件?

使用 Ajax 以一种形式上传数据和文件?

Qt5 多线程:信号仅以一种方式工作

以一种有效的方式使用 ByteBuffer 将标题和数据布局打包在一个字节数组中?