Spring'sReReestBody предоставляет пустую строку на POST - PullRequest
8 голосов
/ 27 апреля 2011

У меня есть приложение на Spring 3.0.5.RELEASE, пытающееся получить полное содержание сообщения, используя @RequestBody. Метод вызывается, но переданная строка всегда пуста. Установив точки останова, я проверил, что вызывается StringHttpMessageConverter, но внутреннее HttpInputMessage пусто.

Я видел эту проблему с Jetty и Tomcat, поэтому я отказываюсь от проблемы с контейнером.

Вот мой пример контроллера:

@Controller
@RequestMapping("/")
public class SubscriptionController {
    @RequestMapping(value = "/requestbody", method = RequestMethod.POST)
    public ModelAndView mycustomAction(@RequestBody String body) {

        // body is always empty
        Logger.getLogger(this.getClass()).debug("REQUEST BODY '" + body + "'");
        return new ModelAndView("empty");
    }
}

Мой контекст приложения определен следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <!-- Enable auto detection of controllers -->
    <context:component-scan base-package="com.big.viajerotelcel.controller" />

    <!--
        use annotation driven mvc and one single validator with JSR-303
        standard
    -->
    <mvc:annotation-driven />

    <!--
        Message source for this context, loaded from localized "messages_xx"
        files
    -->

    <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basenames" value="classpath:i18n/messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>

    <!-- Declare the Interceptor -->
    <mvc:interceptors>
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"
            p:paramName="locale" />
    </mvc:interceptors>

    <!-- Declare the Resolver -->
    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.SessionLocaleResolver" />

    <!-- will load Tiles definitions! -->
    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/general.xml</value>
            </list>
        </property>
    </bean>

    <!-- Tiles view resolver -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

    <!-- Configure the multipart resolver -->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--
            one of the properties available; the maximum file size in bytes (5MB)
        -->
        <property name="maxUploadSize" value="5120000" />
    </bean>

    <!-- Adding these lines has no effect, the StringHttpMessageConverter is called either way -->
<!--    <bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"/>-->
<!--           -->
<!--    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">-->
<!--        <property name="messageConverters">-->
<!--          <list>-->
<!--            <ref bean="stringHttpMessageConverter"/>-->
<!--          </list>-->
<!--        </property>-->
<!--    </bean>-->
</beans>

Я проверяю это с помощью curl следующим образом:

curl -d asd = 123 -d qwe = 456 http://localhost:8080/requestbody

Любые идеи или помощь приветствуются!

Ответы [ 4 ]

7 голосов
/ 27 апреля 2011

Вот фрагмент кода ServletServerHttpRequest, который расширяет HttpInputMessage.Я весьма уверен, что это реализация, которую вы используете в своем коде:

public InputStream getBody() throws IOException {
    return this.servletRequest.getInputStream();
}

Другими словами, тело запроса предназначено для чтения в качестве входного потока объекта HttpServletRequest.

Поток ввода запроса недопустим в нескольких ситуациях, но я не могу найти правильную документацию для него в данный момент.Например, если вы вызываете request.getParameter() для запроса на публикацию, tomcat должен прочитать входной поток, чтобы интерпретировать параметры, поэтому после чтения входного потока он будет пустым, поскольку он уже достиг конца.

Возможно, вы вызываете getParameter где-то в перехватчике или, возможно, в фильтре, определенном в web.xml.Другой вариант заключается в том, что Spring делает это для вас, например, если у вашего контроллера есть какой-то другой метод со сложными @RequestMapping s (такими как чтение значений параметров или значений заголовков).

У меня есть два предложения дляyou:

  1. Добавьте фильтр сервлетов (до того, как у Spring появится возможность действовать) и оберните запрос своей собственной оболочкой (просто добавьте HttpServletRequestWrapper ).Таким образом, вы можете устанавливать точки останова или регистрировать сообщения в некоторых методах объекта запроса и видеть, кто их вызывает.

  2. Используйте параметр объекта pojo и настройте привязки.Похоже, гораздо более чистый способ чтения данных.

0 голосов
/ 19 сентября 2018

Еще одна причина, по которой ваш XML может не направляться в ваш объект JAXB, связана с пространствами имен в XML.

Версии java после 1.8.101 более строги в разборе XML с пространством имен.Смотрите JAXB не отменяет маршалинг после обновления java с 1.8.0_77 до 1.8.0_121

В моем случае я видел тело запроса со всеми нулями и no исключениебросается, чтобы указать, что синтаксический анализ XML не удался.

0 голосов
/ 17 февраля 2013

Была похожая проблема - строка, полученная контроллером пружины, всегда была пустой. Повозился с моим весенним конфигом, но безрезультатно. Наконец проблема заключалась в том, что клиент на самом деле не отправлял что-либо тело! (Из-за какой-то моей опечатки)

Если обнаружена похожая ошибка, стоит один раз проверить, является ли полезная нагрузка клиента не пустой.

0 голосов
/ 27 апреля 2011

Как вы размещаете сообщения на этот URL? Вы уверены, что HTTP-запрос содержит то, что вы думаете, что он делает? Я предлагаю удалить любые веб-браузеры с картинки и перейти на что-то низкоуровневое, например curl, которое позволяет вам отправлять любые типы HTTP-сообщений самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...