【问题标题】:Spring MVC method handling json and form paramsSpring MVC 方法处理 json 和表单参数
【发布时间】:2012-12-01 05:06:17
【问题描述】:

我希望在单个 spring mvc 方法中处理内容类型 application/x-www-form-urlencoded 和 application/json。

我在休息服务中要求接受输入作为表单参数或 json。我可以通过编写两种方法来实现这一点。无论是 params 还是 json,响应总是 json。

@RequestMapping (method = RequestMethod.POST, produces = {"application/json"},
        consumes = {"application/x-www-form-urlencoded"})
public @ResponseBody Book createBook(Book book)
        throws Exception {
    return book;
}

@RequestMapping (method = RequestMethod.POST, produces = {"application/json"},
        consumes = {"application/json"})
public @ResponseBody Book createBookJSON(@RequestBody Book book)
        throws Exception {
    return book;
} 

是否可以将这两种方法合二为一并使其发挥作用?任何帮助都感激不尽。

编辑

我已经实现了相同的,我的控制器和配置如下,但是当我发送 json 请求时,我得到空值作为响应。

当我发送表单参数时,它工作正常。帮我找出问题。

控制器方法

 @RequestMapping (method = RequestMethod.POST, produces = {"application/json", "application/xml"}, consumes = {"application/x-www-form-urlencoded", "application/json"})                   
    public @ResponseBody Book createBook(Book book)
            throws Exception {
        return book;
    }

servlet 上下文

<mvc:view-controller path="/" view-name="index"/>

<context:annotation-config />

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <property name="order" value="1" />
    <property name="mediaTypes">
        <map>
            <entry key="xml" value="application/xml" />
            <entry key="json" value="application/json" />
        </map>
    </property>
    <property name="defaultViews">
        <list>
            <!-- JSON View -->
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />

            <!-- JAXB XML View -->
            <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
                <constructor-arg>
                    <ref bean="jaxb2Marshaller" />
                </constructor-arg>
            </bean>

        </list>
    </property>
    <property name="ignoreAcceptHeader" value="true" />
</bean>

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" >
    <property name="order" value="1" />
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" >
                <property name="supportedMediaTypes" value="application/json"/>
            </bean>

            <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                <property name="marshaller" ref="jaxb2Marshaller" />
                <property name="unmarshaller" ref="jaxb2Marshaller" />
                <property name="supportedMediaTypes" value="application/xml"/>
            </bean>

            <bean class = "org.springframework.http.converter.FormHttpMessageConverter">
                <property name="supportedMediaTypes" value = "application/x-www-form-urlencoded" />
            </bean>

            <bean class = "org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
            </bean>
        </list>
    </property>
</bean>

<bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
    <property name="classesToBeBound">
        <list>
            <value>com.lt.domain.Book</value>
        </list>
    </property>
</bean>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="order" value="2" />
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
</bean>

【问题讨论】:

    标签: java json jakarta-ee spring-mvc


    【解决方案1】:
    @RequestMapping (method = RequestMethod.POST)
    public Book createBook(Book book)
            throws Exception {
        return book;
    }
    

    consumes 接受它可以使用的任何字符串数组,spring bean 绑定应该处理其余部分。问题可能是您没有正确设置 bean 绑定以便自动编组和解组 json。恕我直言,使用 @RequestBody 和 @RepsonseBody 并不是最好的选择。

    确保将 jackson 添加到您的依赖项中

    <dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>latest</version>
    </dependency>
    

    并使用内容协商视图解析器

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="htm" value="text/htm"/>
                <entry key="html" value="text/html"/>
                <entry key="json" value="application/json"/>
            </map>
        </property>
        <property name="viewResolvers">
            <list>
                <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
                <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/jsp/"/>
                    <property name="suffix" value=".jsp"/>
                </bean>
            </list>
        </property>
    
        <property name="defaultViews">
            <list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>
    
            </list>
        </property>
    </bean>
    

    确保在您的客户端应用程序中将接受标头设置为所需的值。 您还应该能够在 requestmethod 注释中删除所有生产和消费数据

    【讨论】:

    • 我已按照您的建议实施。用我面临的问题更新了问题。请建议我哪里出错了。
    • 您收到的对象是 null 吗?您还应该删除 @responsebody 注释。
    • 如果我以 json 格式发送请求,我收到的对象属性为 null。如果我将请求作为表单参数发送,它工作得很好。如果我删除响应正文注释,则会收到 404 错误。
    【解决方案2】:

    如果您希望 spring 自动从 JSON 转换为您的对象,您必须使用 @RequestBody。如果您不使用它,则不会绑定值,并且所有参数都为空,如您在 JSON 中发送时所描述的那样。

    如果您使用@RequestBody:在幕后使用 MessageConverters 完成转换,如 spring 文档中所述:http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestbody

    您正在正确配置 MappingJacksonHttpMessageConverter,它会将 JSON 转换为您的对象。

    缺少的是从表单数据到对象的转换: 您注册了FormHttpMessageConverter,但根据文档,这与您期望的不同。它使用 x-www-form-urlencode 将请求转换为 MultiValueMap&lt;String, String&gt; 而不是您的自定义对象。

    我目前的理解是,您必须编写类似于MappingJacksonHttpMessageConverter 但只能处理表单数据的内容。

    【讨论】:

    • 我一直在阅读以删除我的@RequestBody,但事实证明它确实使事情变得有效!
    猜你喜欢
    • 1970-01-01
    • 2011-06-27
    • 2015-10-16
    • 2014-11-10
    • 2016-01-08
    • 2015-07-31
    • 1970-01-01
    • 2018-07-06
    • 1970-01-01
    相关资源
    最近更新 更多