Spring MVC: сложный объект как GET @RequestParam
Предположим, у меня есть страница, на которой перечислены объекты в таблице, и мне нужно поместить форму для фильтрации таблицы. Фильтр отправляется как Ajax получить URL-адрес, как это:http://foo.com/system/controller/action?page=1&prop1=x&prop2=y&prop3=z
и вместо того, чтобы иметь много параметров, на мой контроллер, как:
@RequestMapping(value = "/action")
public @ResponseBody List<MyObject> myAction(
@RequestParam(value = "page", required = false) int page,
@RequestParam(value = "prop1", required = false) String prop1,
@RequestParam(value = "prop2", required = false) String prop2,
@RequestParam(value = "prop3", required = false) String prop3) { ... }
а если я Мой_объект как:
public class MyObject {
private String prop1;
private String prop2;
private String prop3;
//Getters and setters
...
}
Я хочу сделать что-то вроде:
@RequestMapping(value = "/action")
public @ResponseBody List<MyObject> myAction(
@RequestParam(value = "page", required = false) int page,
@RequestParam(value = "myObject", required = false) MyObject myObject,) { ... }
это возможно? Как я могу это сделать?
3 ответов
вы можете абсолютно это сделать, просто удалите @RequestParam
аннотация, Spring чисто свяжет ваши параметры запроса с вашим экземпляром класса:
public @ResponseBody List<MyObject> myAction(
@RequestParam(value = "page", required = false) int page,
MyObject myObject)
Я добавлю несколько коротких примеров от меня.
класс DTO:
public class SearchDTO {
private Long id[];
public Long[] getId() {
return id;
}
public void setId(Long[] id) {
this.id = id;
}
// reflection toString from apache commons
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
отображение запроса внутри класса контроллера:
@RequestMapping(value="/handle", method=RequestMethod.GET)
@ResponseBody
public String handleRequest(SearchDTO search) {
LOG.info("criteria: {}", search);
return "OK";
}
запрос:
http://localhost:8080/app/handle?id=353,234
результат:
[http-apr-8080-exec-7] INFO c.g.g.r.f.w.ExampleController.handleRequest:59 - criteria: SearchDTO[id={353,234}]
надеюсь, это поможет:)
UPDATE / KOTLIN
потому что в настоящее время я много работаю с Котлином, если кто-то хочет определить аналогичный DTO, класс в Котлине должен иметь следующее форма:
class SearchDTO {
var id: Array<Long>? = arrayOf()
override fun toString(): String {
// to string implementation
}
}
С data
класса, как этот:
data class SearchDTO(var id: Array<Long> = arrayOf())
Весна (протестирована при загрузке) возвращает следующую ошибку для запроса, упомянутого в ответе:
"не удалось преобразовать значение типа 'Java.ленг.String [] ' к требуемому типу 'Ява.ленг.Long []'; вложенное исключение Ява.ленг.NumberFormatException: для входной строки: \ " 353,234\""
класс данных будет работать только для следующих запрос параметры форма:
http://localhost:8080/handle?id=353&id=234
имейте это в виду!
у меня очень похожая проблема. На самом деле проблема глубже, чем я думал. Я использую jquery $.post
использует Content-Type:application/x-www-form-urlencoded; charset=UTF-8
по умолчанию. К сожалению, я основывал свою систему на этом и когда мне нужен сложный объект как @RequestParam
Я не мог просто сделать так, чтобы это произошло.
в моем случае я пытаюсь отправить пользовательские настройки с чем-то вроде;
$.post("/updatePreferences",
{id: 'pr', preferences: p},
function (response) {
...
на стороне клиента фактические необработанные данные, отправленные на сервер;
...
id=pr&preferences%5BuserId%5D=1005012365&preferences%5Baudio%5D=false&preferences%5Btooltip%5D=true&preferences%5Blanguage%5D=en
...
парсится as;
id:pr
preferences[userId]:1005012365
preferences[audio]:false
preferences[tooltip]:true
preferences[language]:en
и серверная сторона;
@RequestMapping(value = "/updatePreferences")
public
@ResponseBody
Object updatePreferences(@RequestParam("id") String id, @RequestParam("preferences") UserPreferences preferences) {
...
return someService.call(preferences);
...
}
пробовал @ModelAttribute
, добавлен сеттер / геттеры, конструкторы со всеми возможностями для UserPreferences
но нет шансов, поскольку он распознал отправленные данные как 5 параметров, но на самом деле сопоставленный метод имеет только 2 параметра. Я также попробовал решение Biju, однако происходит то, что spring создает объект UserPreferences с конструктором по умолчанию и не заполняет данные.
я решил проблему, отправив JSON-строка настроек со стороны клиента и обрабатывает ее как строку на стороне сервера;
клиент:
$.post("/updatePreferences",
{id: 'pr', preferences: JSON.stringify(p)},
function (response) {
...
сервер:
@RequestMapping(value = "/updatePreferences")
public
@ResponseBody
Object updatePreferences(@RequestParam("id") String id, @RequestParam("preferences") String preferencesJSon) {
String ret = null;
ObjectMapper mapper = new ObjectMapper();
try {
UserPreferences userPreferences = mapper.readValue(preferencesJSon, UserPreferences.class);
return someService.call(userPreferences);
} catch (IOException e) {
e.printStackTrace();
}
}
чтобы кратко, я сделал преобразование вручную внутри метода REST. На мой взгляд, причина, по которой spring не распознает отправленные данные,-это тип контента.