Java Spring REST API处理许多可选参数 [英] Java Spring REST API Handling Many Optional Parameters

查看:1286
本文介绍了Java Spring REST API处理许多可选参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently messing around with a Spring Boot REST API project for instructional purposes. I have a rather large table with 22 columns loaded into a MySQL database and am trying to give the user the ability to filter the results by multiple columns (let's say 6 for the purposes of this example).

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

I am currently extending a Repository and have initialized methods such as findByParam1 and findByParam2 and findByParam1OrderByParam2Desc and etc. and have verified that they are working as intended. My question to you guys is the best way to approach allowing the user the ability to leverage all 6 optional RequestParams without writing a ridiculous amount of conditionals/repository method variants. For example, I want to give the user the ability to hit url home/get-data/ to get all results, home/get-data?param1=xx to filter based on param1, and potentially, home/get-data?param1=xx&param2=yy...&param6=zz to filter on all the optional parameters.

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

For reference, here is what the relevant chunk of my controller looks like (roughly).

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

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

My issue so far is that the way I am proceeding about this means that I will basically need n! amount of methods in my repository to support this functionality with n equalling the amount of fields/columns I want to filter on. Is there a better way to approach handling this, perhaps where I am filtering the repository 'in-place' so I can simply filter 'in-place' as I check the Map to see what filters the user did indeed populate?

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

So I'm currently implementing a 'hacky' solution that might be related to J. West's comment below. I assume that the user will be specifying all n parameters in the request URL and if they do not (for example, they specify p1-p4 but not p5 and p6) I generate SQL that just matches the statement to LIKE '%' for the non-included params. It would look something like...

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

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

and in the Controller, I would detect if p5 and p6 were null in the Map and if so, simply change them to the String '%'. I'm sure there is a more precise and intuitive way to do this, although I haven't been able to find anything of the sort yet.

推荐答案

您可以使用 JpaSpecificationExecutor 和自定义规范 https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

You can do this easily with a JpaSpecificationExecutor and a custom Specification: https://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

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

I would replace the HashMap with a DTO containing all optional get params, then build the specifications based on that DTO, obviously you can also keep the HashMap and build the specification based on it.

基本上:

public class VehicleFilter implements Specification<Vehicle>
{
    private String art;
    private String userId;
    private String vehicle;
    private String identifier;

    @Override
    public Predicate toPredicate(Root<Vehicle> root, CriteriaQuery<?> query, CriteriaBuilder cb)
    {
        ArrayList<Predicate> 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<Vehicle, Integer>, JpaSpecificationExecutor<Vehicle>
{
}

只是一个根据公司代码改编的快速示例,你得到想法!

Just a quick example adapted from company code, you get the idea!

这篇关于Java Spring REST API处理许多可选参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆