Java Spring REST API处理许多可选参数

我目前正忙着使用Spring Boot REST API项目进行教学。 我有一个相当大的表,其中22列被加载到MySQL数据库中,并且我试图让用户能够按多列过滤结果(假设这个示例的目的是6)。

我目前正在扩展一个Repository并初始化了一些方法,例如findByParam1和findByParam2以及findByParam1OrderByParam2Desc等,并且已经validation它们是按预期工作的。 我向你们提出的问题是最好的方法,允许用户能够利用所有6个可选的RequestParams,而无需编写大量的条件/存储库方法变体。 例如,我想让用户能够点击url home / get-data /获取所有结果,home / get-data?param1 = xx根据param1进行过滤,可能还有home / get-data?param1 = xx&param2 = yy …&param6 = zz来过滤所有可选参数。

作为参考,这是我的控制器的相关块(粗略地)的样子。

@RequestMapping(value = "/get-data", method = RequestMethod.GET) public List getData(@RequestParam Map params) { String p1 = params.get("param1"); if(p1 != null) { return this.someRepository.findByParam1(p1); } return this.someRepository.findAll(); } 

到目前为止我的问题是我正在进行的这种方式意味着我基本上需要n! 我的存储库中支持此function的方法数量,n等于我想要过滤的字段/列数量。 有没有更好的方法来处理这个问题,也许我正在过滤存储库’就地’,所以我可以简单地过滤’就地’,因为我检查地图以查看用户确实填充了哪些filter?

编辑:所以我正在实施一个’hacky’解决方案,可能与J. West的评论有关。 我假设用户将在请求URL中指定所有n个参数,如果它们没有(例如,它们指定p1-p4但不指定p5和p6),我生成的SQL只匹配LIKE’%’的语句非包含的参数。 它看起来像……

 @Query("select u from User u where u.p1 = :p1 and u.p2 = :p2 ... and u.p6 = :p6") List findWithComplicatedQueryAndSuch; 

在Controller中,我会检测地图中p5和p6是否为空,如果是,则只需将它们更改为字符串’%’即可。 我确信有更精确和直观的方法来做到这一点,虽然我还没有找到任何类型的东西。

您可以使用JpaSpecificationExecutor和自定义Specification轻松完成此操作: https : JpaSpecificationExecutor

我将用包含所有可选get参数的DTO替换HashMap,然后基于该DTO构建规范,显然您还可以保留HashMap并基于它构建规范。

基本上:

 public class VehicleFilter implements Specification { private String art; private String userId; private String vehicle; private String identifier; @Override public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) { ArrayList predicates = new ArrayList<>(); if (StringUtils.isNotBlank(art)) { predicates.add(cb.equal(root.get("art"), art)); } if (StringUtils.isNotBlank(userId)) { predicates.add(cb.equal(root.get("userId"), userId)); } if (StringUtils.isNotBlank(vehicle)) { predicates.add(cb.equal(root.get("vehicle"), vehicle)); } if (StringUtils.isNotBlank(identifier)) { predicates.add(cb.equal(root.get("identifier"), fab)); } return predicates.size() <= 0 ? null : cb.and(predicates.toArray(new Predicate[predicates.size()])); } // getter & setter } 

和控制器:

 @RequestMapping(value = "/{ticket}/count", method = RequestMethod.GET) public long getItemsCount( @PathVariable String ticket, VehicleFilter filter, HttpServletRequest request ) throws Exception { return vehicleService.getCount(filter); } 

服务:

 @Override public long getCount(VehicleFilter filter) { return vehicleRepository.count(filter); } 

库:

 @Repository public interface VehicleRepository extends JpaRepository, JpaSpecificationExecutor { } 

只是一个根据公司代码改编的简单示例,您就会明白这一点!

编码较少的另一种解决方案是使用QueryDsl与Spring MVC集成。

通过使用此方法,您的所有请求参数都将自动解析为您的某个域属性并附加到您的查询中。

有关参考,请参阅文档https://spring.io/blog/2015/09/04/what-s-new-in-spring-data-release-gosling#querydsl-web-support和示例项目https:// github.com/spring-projects/spring-data-examples/tree/master/web/querydsl