Может ли Spring MVC иметь параметры запроса для метода HTTP PUT или я должен использовать post? Что я должен использовать, чтобы быть RESTful?

У меня есть действие контроллера, которое, я думаю, должно быть HTTP PUT, но Spring жалуется, когда я пытаюсь использовать @RequestParam в действии контроллера. Не разрешены ли параметры запроса для методов HTTP PUT, и поэтому Spring отклоняет их?

@RequestMapping(value = "/{helpDocumentId}/vote", method = RequestMethod.PUT)
public void voteHelpfulness(@PathVariable long helpDocumentId, @RequestParam boolean isHelpful) {
    helpManager.voteOnHelpDocument(helpDocumentId, isHelpful);
}

При выполнении выдает такую ​​ошибку:

org.springframework.web.bind.MissingServletRequestParameterException: Required boolean parameter 'isHelpful' is not present

Конечно, параметр isHelpful присутствует. Я могу сделать так, чтобы приведенный выше код отлично работал для HTTP POST, поэтому я знаю, что это не проблема.

     $.ajax({
            url: "/help/" + helpDocumentId + "/vote.json",
            type: "PUT",
            data: {
                isHelpful: isHelpful
            },
            success: function(response) {
                // ....
            }
     });

Является ли PUT правильным методом http? Это действие изменяет helpDocument, но не создает его.


person egervari    schedule 23.11.2011    source источник
comment
jira.springsource.org/browse/SPR-7030   -  person digitaljoel    schedule 24.11.2011
comment
Чёрт возьми, я ненавижу жуков весной. Всегда застревает! Спасибо   -  person egervari    schedule 24.11.2011
comment
Согласованный. Я все еще ищу, надеюсь, что это не единственное решение...   -  person digitaljoel    schedule 24.11.2011
comment
@digitaljoel, довольно поздно, но с Spring 3.1 есть HttpPutFormContentFilter.   -  person Arjan    schedule 28.01.2013
comment
@Arjan Полезно знать. Я просто ПОМЕЩАЮ данные как JSON в тело и обрабатываю их оттуда, используя аннотацию RequestBody. Нет необходимости в каких-либо фильтрах, и это просто работает ™   -  person digitaljoel    schedule 28.01.2013
comment
Да, @digitaljoel, я также использую @RequestBody во многих местах, и даже мои тесты MockMvc были в порядке. Пока один контроллер фактически не использовал @RequestParam, который все еще отлично работал с perform(put(...).param("name", "value")) MockMvc, но не работал при фактическом развертывании в контейнере сервлетов... :-)   -  person Arjan    schedule 28.01.2013
comment
Что ж, @digitaljoel, это просто работает™ при использовании правильного типа для @RequestBody ;-) (Только что увидел проблему с попыткой обработать входящий JSON с помощью @RequestBody MultiValueMap<String, String>.)   -  person Arjan    schedule 30.01.2013
comment
О, @digitaljoel, возможно, Spring/Jackson действительно может сопоставить JSON с (вложенным) MultiValueMap. Если вы знаете, посмотрите комментарии здесь< /а>. Сопоставляете ли вы с каким-то пользовательским типом, простой строкой или чем-то общим?   -  person Arjan    schedule 30.01.2013


Ответы (4)


Начиная с Spring 3.1, HttpPutFormContentFilter можно использовать для обработки application/x-www-form-urlencoded данных:

Фильтр, который делает закодированные данные формы доступными через семейство методов ServletRequest.getParameter*() во время HTTP-запросов PUT.

Спецификация сервлета требует, чтобы данные формы были доступны для HTTP POST, но не для запросов HTTP PUT. Этот фильтр перехватывает HTTP-запросы PUT с типом контента 'application/x-www-form-urlencoded', считывает содержимое, закодированное в форме, из тела запроса и упаковывает ServletRequest, чтобы сделать данные формы доступными в качестве параметров запроса, как это делается для HTTP-запросов POST.

Для других входящих данных, таких как JSON, вам понадобится @RequestBody, как описано в JQuery, Spring MVC @RequestBody и JSON — совместная работа, чтобы не столкнуться с 415 Unsupported Media Type.

person Arjan    schedule 28.01.2013

Контроллеры Spring поддерживают GET/HEAD/POST/PUT/DELETE/OPTIONS/TRACE, но, поскольку ваш браузер не может отправлять эти методы запроса, он не будет работать для вас.

Обходной путь — использовать "org.springframework.web.filter.HiddenHttpMethodFilter", предоставленный Spring. Это требует, чтобы вы передали скрытый параметр для метода запроса. Параметр по умолчанию, поддерживаемый этим фильтром, — «_method».

Проверьте javadoc фильтра для получения дополнительной информации.

person praveenj    schedule 05.12.2011

Это, как было сказано выше, похоже на ошибку в spring/servlet API. На самом деле запросы PUT должны работать с Request Body (or payload), а не с параметрами запроса. В этом смысле API сервлета и обработка Spring верны.

Сказав это, лучший и гораздо более простой обходной путь — не передавать элемент данных из вашего вызова javascript/jQuery и передавать ваши параметры как часть самого URL-адреса. то есть установите параметры в поле URL-адреса так, как вы бы сделали это в вызове GET.

$.ajax({
            url: "/help/" + helpDocumentId + "/vote.json" + "?param1=param2Val&..",
            type: "PUT",
            data: "",
            success: function(response) {
                // ....
            }
     });

теперь это работает для простых параметров, я думаю, не будет работать для сложных типов JSON. Надеюсь это поможет.

person Ravi Bhatt    schedule 20.01.2012

Я последовал рекомендации в комментариях и изменил @RequestParam на @RequestBody, и это просто сработало (мой параметр - строка).

Я согласен, что это ошибка в Spring, потому что точно такой же код, который дает сбой в моей производственной среде (при использовании @RequestParam), отлично работает в локальном хосте.

person AntonioOtero    schedule 26.01.2015