如何使用 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 是的。建议使用单独的参数limit
和offset
进行分页。来源: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 以一种宁静的方式过滤数据?的主要内容,如果未能解决你的问题,请参考以下文章