首页 > 解决方案 > 如何在spring boot中按模型而不是多个参数进行过滤

问题描述

我有一个端点,它列出了对象并通过我们添加的请求参数对其进行查询。有些值是可选的。当过滤值的数量增加时,代码看起来更难看。我正在寻找一个看起来也不错的解决方案。

http://localhost:port/v1/actions?type=1&from=x&to=y&userId=z&adminId

而不是在我的控制器中有很多参数,比如:

@RequestMapping(value = "/action")
  public List<Actions> get(@RequestParam(value = "type") Optional<ActionType> actionType,
                             @RequestParam(value = "from") @DateTimeFormat(pattern = "MMddyyyy") Optional<Date> from,
                             @RequestParam(value = "to") @DateTimeFormat(pattern = "MMddyyyy") Optional<Date> to,
                             @RequestParam(value = "userId") Optional<UUID> userId,
                             @RequestParam(value = "adminId") UUID adminId) {
    return handler.getActions(type, from, to, userId, adminId);

还没有找到任何解决方案。也许这样的事情会很酷。拥有一个模型并注释它们将如何调用查询参数:

public class QueryObject {
    @RequestParam(value = "type") Optional<ActionType> type;
    @RequestParam(value = "from") @DateTimeFormat(pattern = "MMddyyyy") Optional<Date> from;
    @RequestParam(value = "to") @DateTimeFormat(pattern = "MMddyyyy") Optional<Date> to;
     @RequestParam(value = "userId") Optional<UUID> userId;
     @RequestParam(value = "adminId") UUID adminId;

    //Getters and setters
    ...
}

像这样的东西会很酷:

@RequestMapping(value = "/action")
public List<actions> get(
    QueryObject object,
    ) { return handler.getActions(object); }

如果你有什么建议?有可能做到吗?

标签: spring-mvcspring-bootannotationsspring-annotations

解决方案


这种情况相当普遍。因此,最好只有一个查询参数,该参数将采用“形式的字符串值” key1::value1|key2::value2|key3::value3| ...。然后为控制器方法编写一个解析器,该解析器将生成查询参数(键)及其值的映射。这是最好的练习处理查询参数。

这是一个例子:

@RequestMapping(method = RequestMethod.GET, path="/search-products")
public ProductInfoListResponse searchProducts(@RequestParam(name = "filter", required = false) String filter) {

            final String[] QUERY_FILTER_KEYS = { "name", "type", "minCostPrice", "maxCostPrice" };

            Map<String, String> keyValueMap = getKeyValuePairFromFilter(filter, QUERY_FILTER_KEYS);

            for (String key : keyValueMap.keySet()) {
                 String value = keyValueMap.get(key);
                 //Process values here

                case "name":
                ...
                break;
                case "type":
                ...
                break;
            }
    }

public Map<String, String> getKeyValuePairFromFilter(final String filter, final String[] validFilterKeys) {

         final String QUERY_FILTER_PATTERN = "^(?:\\s*((?:[^\\:\\:\\|\\s]+\\s+)*[^\\:\\:\\|\\s]+)\\s*\\:\\:\\s*((?:[^\\:\\:\\|\\s]+\\s+)*[^\\:\\:\\|\\s]+)\\s*(?:\\|(?!\\s*$)|$))+$";

        final String QUERY_PARAM_PAIR_DELIMITER = "\\|";
        final String QUERY_PARAM_VALUE_DELIMITER = "::";

        Map<String, String> map = new LinkedHashMap<>();

        if (!StringUtils.isEmpty(filter)) {

            if (!filter.matches(QUERY_FILTER_PATTERN)) {

                throw BadRequestException.parameterInvalidExpectedValue("filter",
                        "key1::value1|key2::value2|key3::value3...");
            }

            String[] queryParamArray = filter.split(QUERY_PARAM_PAIR_DELIMITER);

            if (!StringUtils.isEmpty(queryParamArray)) {

                List<String> validQueryParamList = Arrays.asList(validFilterKeys);

                for (int i = 0; i < queryParamArray.length; i++) {

                    String queryParamPair = queryParamArray[i];

                    if (!StringUtils.isEmpty(queryParamPair)) {
                        String[] queryParamPairArray = queryParamPair.split(QUERY_PARAM_VALUE_DELIMITER);

                        if (!StringUtils.isEmpty(queryParamPairArray) && queryParamPairArray.length == 2) {
                            String key = queryParamPairArray[0].trim();
                            if (validQueryParamList.contains(key)) {
                                String valueText = queryParamPairArray[1].trim();
                                logger.debug("Adding key:value pair in the map: [{} : {}]", key, valueText);
                                map.put(key, valueText);
                            }
                        }
                    }
                }
            }
        }

        return map;
    }

推荐阅读