我知道Spring MVC可以轻松返回Json格式的模型;但是,我尝试了很多不同的方法来返回CSV格式的模型(通过杰克逊),但无法成功。
我该怎么办?
我附上我的模型代码,控制器代码和gradle.build,如下所示:
非常感谢!
型号:
@JsonPropertyOrder({ "staffName", "name" })
public class Greeter
{
String name;
String staffName[];
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String[] getStaffName()
{
return staffName;
}
public void setStaffName(String[] staffName)
{
this.staffName = staffName;
}
}
控制器:
@Controller
public class GreetingController {
@RequestMapping(value = "/greeter/json", method = RequestMethod.GET)
public @ResponseBody
Greeter getGreeterInJSON() {
Greeter greeter = new Greeter();
greeter.setName("default");
greeter.setStaffName(new String[] { "ye", "lichi" });
return greeter;
}
@RequestMapping(value = "/greeter/csv", method = RequestMethod.GET, consumes = "text/csv")
public @ResponseBody
Greeter getGreeterInCSV(HttpServletResponse response) {
Greeter greeter = new Greeter();
greeter.setName("default");
greeter.setStaffName(new String[] { "ye", "lichi" });
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper.schemaFor(Greeter.class);
ObjectWriter writer = mapper.writer(schema.withLineSeparator("\n"));
File greeterCSV = new File("greeterCSV.csv");
try {
writer.writeValue(greeterCSV, greeter);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return greeter;
}
}
build.gradle依赖项:
dependencies {
compile group: 'commons-collections', name: 'commons-collections', version: '3.2'
compile ('org.springframework:spring-context:4.0.0.RELEASE')
compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M6")
compile("org.thymeleaf:thymeleaf-spring3:2.0.17")
// compile "org.codehaus.jackson:jackson-mapper-asl:1.9.13"
compile 'com.fasterxml.jackson.core:jackson-databind:2.3.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.3.0'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.3.0'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-csv:2.3.0'
testCompile group: 'junit', name: 'junit', version: '4.+'
testCompile "org.mockito:mockito-all:1.9.5"
}
编辑:
Tomcat错误:
HTTP状态415 -
输入状态报告
消息
描述服务器拒绝了此请求,因为请求实体的格式不受所请求方法所请求资源的支持。
答案 0 :(得分:3)
您不想消费,但生成 csv。你拥有它的方式,服务期望输入以csv格式提供,这就是为什么它抱怨“请求实体的格式不受支持”。关键是“请求” - 它需要一些csv格式的输入。 将“消费”改为“生产”应该可以解决您的问题。
答案 1 :(得分:0)
我一直在寻找这个问题的答案,但遗憾的是没有找到,所以我将在这里举例说明。
您需要添加一个 CSV 消息转换器。此 @Configuration
执行此操作:
@Configuration
public class CsvConfiguration {
@Bean
JacksonToCsvHttpMessageConverter csvMessageConverter() {
CsvMapper mapper = new CsvMapper();
// configure mapper here
mapper.registerModule(new JavaTimeModule());
return new JacksonToCsvHttpMessageConverter(mapper);
}
}
和转换器本身:
请注意,此简化版本不支持过滤器或视图。但是,如果您研究覆盖的方法 writeInternal
,您应该能够添加这些功能,如果您需要它们。此外,不支持空集合,但如果您想支持空系列,可以使用空数组。
public class JacksonToCsvHttpMessageConverter extends AbstractJackson2HttpMessageConverter {
protected JacksonToCsvHttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.parseMediaType("text/csv"));
}
@Override
protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
if (object instanceof MappingJacksonValue) object = ((MappingJacksonValue) object).getValue();
CsvMapper mapper = (CsvMapper) getObjectMapper();
Class<?> klass = getType(object);
CsvSchema schema = mapper.schemaFor(klass).withHeader();
JsonEncoding encoding = getJsonEncoding(outputMessage.getHeaders().getContentType());
try (CsvGenerator generator = mapper.getFactory().createGenerator(outputMessage.getBody(), encoding)) {
ObjectWriter writer = mapper.writer().with(schema);
writer.writeValue(generator, object);
}
}
private Class<?> getType(Object object) {
if (object instanceof Collection) {
Collection<?> c = (Collection<?>) object;
return c.iterator().next().getClass();
}
if (object.getClass().isArray()) return object.getClass().getComponentType();
return object.getClass();
}
}
这将使所有传统的控制器方法都可以通过 Accept
标头的方式返回 CSV。 Accept: application/json
将产生 JSON 而 Accept: text/csv
将产生 CSV。当然,所有的 CsvMapper 约束都将适用,所以没有嵌套对象等。
@RestController
public class CsvController {
@GetMapping("/records*")
public CsvRecord[] getRecords() {
return new CsvRecord[] { new CsvRecord(), new CsvRecord() };
}
@GetMapping("/record")
public CsvRecord getRecord() {
return new CsvRecord();
}
@JsonAutoDetect(fieldVisibility = Visibility.PUBLIC_ONLY)
public static class CsvRecord {
public String name = "aa";
}
}
使用此配置将导致您的应用为 Accept: */*
请求返回 CSV。这很少是有意的,因此您可以通过添加以下配置将默认内容类型设置为 JSON:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON);
}
}
答案 2 :(得分:-2)
您正在使用GET,因此您希望回复的内容为CSV,因此请务必使用produce = &#34; text / csv&#34; 而不是使用=&#34; text / CSV&#34) 在这里: -
@RequestMapping(value = "/greeter/csv", method = RequestMethod.GET, consumes = "text/csv")
public @ResponseBody
我们在发送一些
时使用消费