简体   繁体   English

Spring 的 @RequestBody 在 POST 上提供空字符串

[英]Spring's @RequestBody providing empty string on POST

I have an application with Spring 3.0.5.RELEASE trying to get the full content of a post using @RequestBody.我有一个带有 Spring 3.0.5.RELEASE 的应用程序,试图使用 @RequestBody 获取帖子的全部内容。 The method is called, but the string passed is always empty.该方法被调用,但传递的字符串始终为空。 I have checked, by placing breakpoints, that the StringHttpMessageConverter is called, but the inner HttpInputMessage is empty.我通过放置断点检查了是否调用了 StringHttpMessageConverter,但内部 HttpInputMessage 为空。

I've seen this issue with both Jetty and Tomcat, so I'm discarding it's a problem with the container.我已经在 Jetty 和 Tomcat 中看到了这个问题,所以我放弃了这是容器的问题。

Here is my sample controller:这是我的样品 controller:

@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");
    }
}

My application context is defined as follows:我的应用程序上下文定义如下:

<?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>

I'm testing this using curl as follows:我正在使用 curl 对此进行测试,如下所示:

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

Any ideas or help is more than welcomed!任何想法或帮助都非常受欢迎!

Here is a code snippet of ServletServerHttpRequest , which extends HttpInputMessage .这是ServletServerHttpRequest的代码片段,它扩展了HttpInputMessage I am pretty positive this is the implementation that you are using in your code:我很肯定这是您在代码中使用的实现:

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

In other words, the request body is meant to be read as the input stream of the HttpServletRequest object.换句话说,请求正文将被读取为HttpServletRequest object 的输入 stream。

The request's input stream is not valid in several situations, but I can't find the correct documentation for it at the moment.请求的输入 stream 在几种情况下无效,但我目前找不到正确的文档。 For example, if you call request.getParameter() on a post request, tomcat has to read the input stream in order to interpret the parameters, thus afterwards when you read the input stream, it is empty because it has reached the end already.例如,如果您在发布请求上调用request.getParameter() ,tomcat 必须读取输入 stream 以解释参数,因此之后当您读取输入 ZF7B44CFAFD5C52223D5498196C8A2E 时,它已经为空。

Perhaps you are invoking getParameter somewhere in an interceptor or perhaps a filter defined in web.xml.也许您正在拦截器中的某处调用getParameter ,或者可能是在 web.xml 中定义的过滤器。 Another option is that Spring is doing that for you, for example, if your controller has some other method with complex @RequestMapping s (such as reading param values, or header values).另一种选择是 Spring 正在为您执行此操作,例如,如果您的 controller 具有其他具有复杂@RequestMapping的方法(例如读取参数值或 Z099FB995346F31C743F6E40DB0F359 值)。

I have two suggestions for you:我有两个建议给你:

  1. Add a servlet filter (before spring gets a chance to act), and wrap the request with your own wrapper (just extend HttpServletRequestWrapper ).添加一个 servlet 过滤器(在 spring 有机会采取行动之前),并用您自己的包装器包装请求(只需扩展HttpServletRequestWrapper )。 This way you can put breakpoints or log messages at some methods of the request object and see who's calling them.这样,您可以在请求 object 的某些方法处放置断点或记录消息,并查看谁在调用它们。

  2. Use a pojo object parameter, and setup the bindings.使用 pojo object 参数,并设置绑定。 It seems like a much cleaner way to read post data.这似乎是一种读取帖子数据的更简洁的方法。

Had a similar problem - the string received by spring controller was always empty.有类似的问题 - spring controller 收到的字符串始终为空。 Tinkered with my spring config but with no result.修改了我的 spring 配置,但没有结果。 Finally the problem was that the client was actually was not sending anything body!(due to some typo of mine)最后的问题是客户实际上没有发送任何正文!(由于我的一些错字)

If found with a similar error, its worth checking once if the client's payload is actually non-empty.如果发现有类似的错误,如果客户端的有效负载实际上是非空的,则值得检查一次。

Another reason that your XML may not be getting marshalled into your JAXB object is related to the namespaces in the XML.您的 XML 可能未编组到 JAXB object 的另一个原因与 Z35301BB093D39638 中的命名空间有关。

Versions of java after 1.8.101 are more strict about parsing namespaced XML. 1.8.101 之后的 java 版本对解析命名空间 XML 更加严格。 See JAXB doesn't unmarshall after updating java from 1.8.0_77 to 1.8.0_121请参阅JAXB 在将 java 从 1.8.0_77 更新到 1.8.0_121 后不会解组

In my case I was seeing a request body with all nulls and no exception being thrown to indicate that the XML parsing had failed.在我的情况下,我看到一个请求正文,其中包含所有空值并且没有抛出异常,表明 XML 解析失败。

How are you POSTing messages to this URL?您如何向此 URL 发布消息? Are you positive that the HTTP request contains what you think it does?您确定 HTTP 请求包含您认为的内容吗? I suggest removing any web browsers from the picture and drop down to something low-level like curl which lets you send any type of HTTP message yourself.我建议从图片中删除所有 web 浏览器并下拉到像curl这样的低级别浏览器,这样您就可以自己发送任何类型的 HTTP 消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM