首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Spring MVC 3.1控制器的处理方法中,直接将流转换为响应输出流

在Spring MVC 3.1控制器的处理方法中,直接将流转换为响应输出流
EN

Stack Overflow用户
提问于 2013-03-08 06:50:34
回答 3查看 32.9K关注 0票数 24

我有一个处理ajax调用和返回JSON的控制器方法。我使用来自json.org的JSON库来创建JSON。

我可以执行以下操作:

代码语言:javascript
复制
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public String getJson()
{
    JSONObject rootJson = new JSONObject();

    // Populate JSON

    return rootJson.toString();
}

但是,将JSON字符串放在一起,只让Spring将其写入响应的输出流,效率很低。

相反,我可以将其直接写入响应输出流,如下所示:

代码语言:javascript
复制
@RequestMapping(method = RequestMethod.POST)
public void getJson(HttpServletResponse response)
{
    JSONObject rootJson = new JSONObject();

    // Populate JSON

    rootJson.write(response.getWriter());
}

但似乎有一种更好的方法可以做到这一点,而不是将HttpServletResponse传递给处理程序方法。

有没有其他类或接口可以从处理程序方法中返回,我可以使用它以及@ResponseBody注释?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-03-08 15:50:51

您可以将Output Stream或Writer作为控制器方法的参数。

代码语言:javascript
复制
@RequestMapping(method = RequestMethod.POST)
public void getJson(Writer responseWriter) {
    JSONObject rootJson = new JSONObject();
    rootJson.write(responseWriter);
}

@查看Spring Reference Documentation 3.1 Chapter 16.3.3.1 Supported method argument types

附注:我觉得在测试中使用OutputStreamWriter作为参数仍然比使用HttpServletResponse容易得多-感谢您对what I have written的关注;-)

票数 32
EN

Stack Overflow用户

发布于 2014-08-04 11:21:41

最后,我为此编写了一个HttpMessageConverter。使用它,我可以执行以下操作:

代码语言:javascript
复制
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public JSONObject getJson()
    throws JSONException
{
    JSONObject rootJson = new JSONObject();

    // Populate JSON

    return rootJson;
}

下面是我的HttpMessageConverter类:

代码语言:javascript
复制
package com.example;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

public class JsonObjectHttpMessageConverter
    extends AbstractHttpMessageConverter<JSONObject>
{
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    public JsonObjectHttpMessageConverter()
    {
        super(new MediaType("application", "json"), new MediaType("text", "javascript"));
    }

    @Override
    protected boolean supports(Class<?> clazz)
    {
        return JSONObject.class.equals(clazz);
    }

    @Override
    protected JSONObject readInternal(Class<? extends JSONObject> clazz,
                                      HttpInputMessage            inputMessage)
        throws IOException,
               HttpMessageNotReadableException
    {
        throw new UnsupportedOperationException();
    }

    @Override
    protected void writeInternal(JSONObject        jsonObject,
                                 HttpOutputMessage outputMessage)
        throws IOException,
               HttpMessageNotWritableException
    {
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputMessage.getBody(),
                                                                    getContentTypeCharset(outputMessage)));

        try
        {
            jsonObject.write(writer);
            writer.flush();
        }
        catch (JSONException e)
        {
            throw new HttpMessageNotWritableException(e.getMessage(), e);
        }
    }

    private Charset getContentTypeCharset(HttpMessage message)
    {
        MediaType contentType = message.getHeaders().getContentType();

        Charset charset = (contentType != null) ? contentType.getCharSet() : null;

        return (charset != null) ? charset : DEFAULT_CHARSET;
    }
}

HttpMessageConverter必须注册到Spring.这可以在dispatcher-servlet.xml文件中完成,如下所示:

代码语言:javascript
复制
<beans ...>

    ...    

    <mvc:annotation-driven conversion-service="conversionService" validator="validator">
        <mvc:argument-resolvers>
            ...
        </mvc:argument-resolvers>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>text/plain;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                        <value>*/*</value>
                    </list>
                </property>
                <property name="writeAcceptCharset" value="false" />
            </bean>
            <bean class="com.example.JsonObjectHttpMessageConverter" />
            <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                <property name="objectMapper" ref="jacksonObjectMapper" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

    ...

</beans>

如您所见,我还注册了其他HttpMessageConverter对象。顺序确实很重要。

票数 4
EN

Stack Overflow用户

发布于 2016-10-21 17:56:29

请注意,如果您使用OutputStream或Writer,则需要您自己编写标头。

一种解决方法是使用InputStreamResource/ResourceHttpMessageConverter

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15283347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档