使用消息转换器从 Spring 个控制器返回 CSV 或 JSON

Returning CSV or JSON from Spring Controllers using Message Converters

我正在尝试根据用户请求的媒体类型将我的 Spring 应用程序配置为 return JSON 或 CSV。为此,我设置了如下所示的标签

<context:annotation-config />


<bean id ="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
    <property name="favorPathExtension" value="false"/>
    <property name="favorParameter"  value="true"/>
    <property name="parameterName" value="mediaType"/>
    <property name="defaultContentType"  value="test/csv"/>

    <property name="mediaTypes">
        <map>
            <entry key="json" value="application/json" />
            <entry key="csv" value="test/csv"/>
        </map>
    </property>
</bean>

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
    <mvc:message-converters register-defaults="true">
        <bean class="com.data.api.util.CSVMessageConverter"/>
        <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper">
                <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                    <property name="modules" ref="jodaModule"/>
                    <property name="featuresToDisable">
                        <array>
                            <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS"/>
                        </array>
                    </property>
                    <property name="defaultViewInclusion" value="false"/>
                    <property name="failOnUnknownProperties" value="false"/>
                </bean>

            </property>
            <property name="supportedMediaTypes">
                <array>
                    <util:constant static-field="org.springframework.http.MediaType.ALL" />
                </array>

            </property>
        </bean>
<bean id="jodaModule" class="com.fasterxml.jackson.datatype.joda.JodaModule"/>
    </mvc:message-converters>
</mvc:annotation-driven>

下面是我的 CSVMessageConverter class

public class CSVMessageConverter 扩展 AbstractHttpMessageConverter {

public static final MediaType MEDIA_TYPE = new MediaType("text", "csv", Charset.forName("utf-8"));

public CSVMessageConverter() {
    super(MEDIA_TYPE);
}

@Override
protected boolean supports(Class<?> clazz) {
    return true;
}

@Override
protected CSVMessage readInternal(Class<? extends CSVMessage> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
    CSVReader reader = new CSVReader(new InputStreamReader(inputMessage.getBody()));
    return new CSVMessage(reader.readAll());
}

@Override
protected void writeInternal(CSVMessage message, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    CSVWriter writer = new CSVWriter(new OutputStreamWriter(outputMessage.getBody()));
    if (! Strings.isNullOrEmpty(message.getHeader())) {
        writer.writeNext(new String[] { "#" + message.getHeader() } );
    }
    for (String[] row: message.getRows()) {
        writer.writeNext(row);
    }
    writer.close();
}

}

我的控制器会这样做

public class TestController { 
public @ResponseBody List<Records> getHits(@PathVariable("domain") name  domainName,
                                       @PathVariable("property") Name propertyName,
                                       @RequestParam(value = "start", required = true)  @DateTimeFormat(pattern = datePattern) Date startDate,
                                       @RequestParam(value = "end", required = true) @DateTimeFormat(pattern = datePattern) Date endDate,
                                       HttpServletRequest request) {
//This returns an arralist of records
}    
}

我无法让我的 CSVMessageConverter 工作。它正在抛出无法将 ArrayList 转换为 CSVMessage。我究竟做错了什么 ?它与 JSON 一起工作正常,但如果我请求 "text/csv" 它会爆炸。

有人可以解释一下 Spring 如何使用 MessageConverters 以及我可以做些什么来使上面的代码工作。

我通过修复我的 CSVMessageConverter class 来解决这个问题。它期待 readInternal/WriteExternal 中的 CSVMessage class。我将其更改为 ArrayList.class 并且这些方法被调用得很好。