如何让Spring Controller从POJO返回CSV?

给出一个简单的Java对象:

public class Pojo { private String x; private String y; private String z; //... getters/setters ... } 

是否有一些我可以放在我的项目上的lib,它将构成一个像这样的控制器:

 @RequestMapping(value="/csv", method=RequestMethod.GET, produces= MediaType.TEXT_PLAIN) @ResponseBody public List csv() { //Some code to get a list of Pojo objects //... return myListOfPojos; } 

要生成我的Pojos的csv文件? 对于Json结果,我使用Jackson lib。 我需要另一个用于CSV结果的lib。

作为一个简单的变种。 您可以通过任何方式生成csv并将其作为String返回。

像这样的东西:

 @RequestMapping(value="/csv", method=RequestMethod.GET) @ResponseBody public String csv() { //Some code to get a list of Pojo objects //... StringBuilder sb = new StringBuilder(); for (Pojo pojo: myListOfPojos){ sb.append(pojo.getX()); sb.append(","); sb.append(pojo.getY()); sb.append(","); sb.append(pojo.getZ()); sb.append("\n"); } return sb.toString; } 

应该管用。

通过reflection自动生成此字符串看起来也很简单。

基于另一个问题,我为Tsv响应做了我自己的HTTPMessageConverter。

TsvMessageConverter.java

 public class TsvMessageConverter extends AbstractHttpMessageConverter { public static final MediaType MEDIA_TYPE = new MediaType("text", "tsv", Charset.forName("utf-8")); private static final Logger logger = LoggerFactory.getLogger(TsvMessageConverter.class); public TsvMessageConverter() { super(MEDIA_TYPE); } protected boolean supports(Class clazz) { return TsvResponse.class.equals(clazz); } @Override protected TsvResponse readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null; } protected void writeInternal(TsvResponse tsvResponse, HttpOutputMessage output) throws IOException, HttpMessageNotWritableException { output.getHeaders().setContentType(MEDIA_TYPE); output.getHeaders().set("Content-Disposition", "attachment; filename=\"" + tsvResponse.getFilename() + "\""); final OutputStream out = output.getBody(); writeColumnTitles(tsvResponse, out); if (tsvResponse.getRecords() != null && tsvResponse.getRecords().size() != 0) { writeRecords(tsvResponse, out); } out.close(); } private void writeRecords(TsvResponse response, OutputStream out) throws IOException { List getters = getObjectGetters(response); for (final Object record : response.getRecords()) { for (String getter : getters) { try { Method method = ReflectionUtils.findMethod(record.getClass(), getter); out.write(method.invoke(record).toString().getBytes(Charset.forName("utf-8"))); out.write('\t'); } catch (IllegalAccessException | InvocationTargetException e) { logger.error("Erro ao transformar em CSV", e); } } out.write('\n'); } } private List getObjectGetters(TsvResponse response) { List getters = new ArrayList<>(); for (Method method : ReflectionUtils.getAllDeclaredMethods(response.getRecords().get(0).getClass())) { String methodName = method.getName(); if (methodName.startsWith("get") && !methodName.equals("getClass")) { getters.add(methodName); } } sort(getters); return getters; } private void writeColumnTitles(TsvResponse response, OutputStream out) throws IOException { for (String columnTitle : response.getColumnTitles()) { out.write(columnTitle.getBytes()); out.write('\t'); } out.write('\n'); } } 

TsvResponse.java

 public class TsvResponse { private final String filename; private final List records; private final String[] columnTitles; public TsvResponse(List records, String filename, String ... columnTitles) { this.records = records; this.filename = filename; this.columnTitles = columnTitles; } public String getFilename() { return filename; } public List getRecords() { return records; } public String[] getColumnTitles() { return columnTitles; } } 

在SpringContext.xml上添加以下内容:

      

所以,你可以在控制器上使用这样的:

 @RequestMapping(value="/tsv", method= RequestMethod.GET, produces = "text/tsv") @ResponseBody public TsvResponse tsv() { return new TsvResponse(myListOfPojos, "fileName.tsv", "Name", "Email", "Phone", "Mobile"); }