我有一个端点,该端点列出了对象并通过我们添加的请求参数对其进行查询。一些值是可选的。当过滤值的数量增加时,代码看起来更难看。我正在寻找一种看起来也不错的解决方案。
http://localhost:port/v1/actions?type=1&from=x&to=y&userId=z&adminId
并且在我的Controller中没有很多参数,例如:
@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); }
您有什么建议吗?有可能做到吗?
答案 0 :(得分:-1)
这种情况很常见。因此,总是最好只有一个查询参数,其参数字符串形式为“ 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;
}