Можно ли сопоставить параметры запроса с динамическими именами с помощью Spring Boot? Я хотел бы сопоставить такие параметры, как эти:
/products?filter[name]=foo
/products?filter[length]=10
/products?filter[width]=5
Я мог бы сделать что-то подобное, но для этого нужно было бы знать все возможные фильтры, и я бы хотел, чтобы он был динамичным:
@RestController
public class ProductsController {
@GetMapping("/products")
public String products(
@RequestParam(name = "filter[name]") String name,
@RequestParam(name = "filter[length]") String length,
@RequestParam(name = "filter[width]") String width
) {
//
}
}
Если возможно, я ищу что-то, что позволит пользователю определять любое количество возможных значений фильтра и чтобы они отображались как HashMap с помощью Spring Boot.
@RestController
public class ProductsController {
@GetMapping("/products")
public String products(
@RequestParam(name = "filter[*]") HashMap<String, String> filters
) {
filters.get("name");
filters.get("length");
filters.get("width");
}
}
В ответе, опубликованном на этот вопрос, предлагается использовать @RequestParam Map<String, String> parameters, однако он будет фиксировать параметры запроса все, а не только те, которые соответствуют filter[*].
Связано, но они так и не решили это.




Вам подходят матричные переменные? Если я вас правильно понял, может быть так:
// GET /products/filters;name=foo;length=100
@GetMapping ("/ продукты / фильтры") общественные недействительные продукты ( @MatrixVariable MultiValueMap matrixVars) {
// matrixVars: ["name" : "foo", "length" : 100]
}
Интересно, что я раньше не видел такого способа форматирования параметров запроса. Учитывая, что у него есть собственная аннотация в Spring (@MatrixVariable), возможно, именно так обычно делают службы Spring / Java. Я привык к Rails, в котором используются foo=bar, filter[x]=y, list[]=x&list[]=y, которые я считаю более читаемыми.
Это похоже на решаемую проблему. Насколько я знаю, решения не идеальны, но есть пути.
Предыдущая попытка, казалось, была направлена на поиск идеального решения, при котором весь состав фильтра был известен при транспортировке.
Все динамические критерии, которые определяет пользователь, могут быть переданы с помощью некоторой базовой схемы, которую вы определяете, как один параметр ключ = значение от клиента, а затем разложить на его элементы после его получения.
Вы также можете отправить два параметра: «поля» и «значения», где списки каждого из них закодированы соответственно, с некоторым осторожным разделителем по вашему выбору (возможно, это может быть закодированный специальный символ, который пользователь не может физически ввести, возможно).
Как и во всем другом подходе, когда клиентская сторона отправляет критерии (например, критерии фильтрации), вам по-прежнему требуется полная защита от любого злонамеренного использования параметров, так же как клиент пытается встроить в них критерии SQL (SQL-инъекция).
Но пока клиентский код следует согласованному синтаксису, вы можете получить от них любое количество динамических параметров за один раз.
Клиент:
/products?filter=field1--value1||field2--value2||field3--value3...
Это упрощенный пример, показывающий разделители, которые слишком легко «сломать», но идея заключается в некоторой простой, даже полностью читаемой (без вреда при этом) схеме, предназначенной только для объединения имен ваших полей и значений для облегчения передачи.
Сервер:
@RequestMapping(value = "/products", method = RequestMethod.GET)
public String doTheStuff(@RequestParam(value = "filter") String encodedFilter) {
.. decompose the filter here, filter everything they've sent for disallowed characters etc.
Спасибо за ответ. Я решил отформатировать фильтры, используя то, что я считаю «стандартным» форматированием, и то, что я привык исходить из фона Ruby on Rails. Я бы предпочел формат f[x]=y. Я рекомендую использовать свой собственный стандарт для представления фильтров из-за возможных проблем, которые вы цитируете, таких как SQL-инъекция и обеспечение правильной работы разделителей.
Вы можете сопоставить несколько параметров без определения их имен в @RequestParam, используя карту:
@GetMapping("/api/lala")
public String searchByQueryParams(@RequestParam Map<String,String> searchParams) {
...
}
Возможный дубликат Spring MVC заполняет @RequestParam Map <String, String>