java rest集合参数,Java Spring REST API处理许多可选参数

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).

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 getData(@RequestParam Map params) {

String p1 = params.get("param1");

if(p1 != null) {

return this.someRepository.findByParam1(p1);

}

return this.someRepository.findAll();

}

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?

EDIT: 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 findWithComplicatedQueryAndSuch;

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.

解决方案

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.

Basically:

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

}

And the controller:

@RequestMapping(value = "/{ticket}/count", method = RequestMethod.GET)

public long getItemsCount(

@PathVariable String ticket,

VehicleFilter filter,

HttpServletRequest request

) throws Exception

{

return vehicleService.getCount(filter);

}

Service:

@Override

public long getCount(VehicleFilter filter)

{

return vehicleRepository.count(filter);

}

Repository:

@Repository

public interface VehicleRepository extends JpaRepository, JpaSpecificationExecutor

{

}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值