【问题标题】:How do I filter data in a restful way using Spring?如何使用 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)
        ...
 }

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

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

非常感谢您的帮助。

【问题讨论】:

标签: java spring hibernate rest filter


【解决方案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/…
      猜你喜欢
      • 1970-01-01
      • 2013-01-14
      • 1970-01-01
      • 2012-08-21
      • 1970-01-01
      • 2011-12-10
      • 2011-01-26
      • 2023-04-02
      • 1970-01-01
      相关资源
      最近更新 更多