spring-mvc - 如何在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); }
如果你有什么建议?有可能做到吗?
解决方案
这种情况相当普遍。因此,最好只有一个查询参数,该参数将采用“形式的字符串值” 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;
}
推荐阅读
- odata - 用于删除预订联系人的 Odata 提取
- python - 在通过 MATLAB API for Python 时,方矩阵展平为行向量
- docker - 如何让快速网关在 Kubernetes 中工作?
- android - Jetpack Compose 中的模糊
- react-native - 我无法安装胜利本机 npm 我胜利本机
- java - 如何提高过滤速度?
- linux - 将文件从 .cfg 更改为 .txt
- certificate - 在 openshift 中的路由中使用密钥中的证书和密钥
- python - 按时间和其他列进行 groupby 以获得唯一值
- swift - SwiftUI 中的滚动和翻译冲突