繁体   English   中英

JSP和SPRING Boot:从JSON输入生成CSV文件吗?

[英]JSP and SPRING Boot : Generate CSV file from JSON input?

我做了一些研究,但是找不到解决方法。 当用户单击客户侧的“使用mailId导出记录时”,我希望能够从数据库中将一些记录导出到CSV。 实现此目标的最佳方法是什么? 在我的研究中,我发现人们仅使用Servlet作为示例,但对我而言,我不使用Servlet。

这是我的控制器:

 @RequestMapping(value = "/eblnotif/exportMailId", method = RequestMethod.POST, produces = "application/json")
        public @ResponseBody List<EblNotifResource> exportMailIdCsv(@RequestBody Filters filters)
                throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException,
                SecurityException, IOException {

            List<EblNotif> eblnotif_list = accountSservice.exportMailIdCsv(filters);

            List<EblNotifResource> eblnotifres = new ArrayList<>();

            for (EblNotif eblNotif : eblnotif_list) {
                EblNotifResource eblres = new EblNotifResource();
                eblres.setFormName(eblNotif.getFormName());
                eblres.setSendingDate(eblNotif.getSendingDate());
                eblres.setMode(eblNotif.getMode());
                eblres.setLanguage(eblNotif.getLanguage());
                eblres.setGpart(eblNotif.getGpart());
                eblres.setEmail(eblNotif.getEmail());
                eblres.setMailId(eblNotif.getMailId());
                eblnotifres.add(eblres);
            }
            return eblnotifres;
    }
}

并将此json格式返回给客户端(JSP):

 [
   {
      "formName":"FormName1",
      "mode":"S",
      "language":"F",
      "sendingDate":"2017-04-03",
      "gpart":"555",
      "email":"",
      "mailId":"96318"
   },
   {
      "formName":"FormName2",
      "mode":"S",
      "language":"F",
      "sendingDate":"2017-04-03",
      "gpart":"444",
      "email":"",
      "mailId":"96325"
   }
]

所需的csv输出如下所示:

formName;mode;language;sendingDate;gpart;email;mailId
FormName1;S;F;2017-04-03;555;testing@test;96318
FormName2;S;F;2017-04-03;444;testing@test;96325

如果只需要一次性下载CSV,则在控制器方法内部转换相关对象可能是最简单的选择。 但是,如果需要在多个位置进行这种下载,则将来通过HttpMessageConverter向Spring MVC Rest添加CSV支持可能会更有益。

第1步 :可选,但建议

使用OpenCSVuniVocitySmooks (仅CSV解析器)之类的CSV转换库在CSV之间进行对象转换。 使用良好的库将节省大量样板代码,还可用于扩展对其他格式的支持,例如制表符分隔的值(TSV)和固定宽度的列。

步骤2 :实现GenericHttpMessageConverter

创建GenericHttpMessageConverter的实现,以使用在步骤1中选择的CSV转换库将对象与CSV相互转换。此步骤有点棘手,因为HttpMessageConverter通常用于将单个对象转换为所需的内容类型,而CSV内容是对象的集合(每行代表一个对象)。 但是,Spring团队在Jaxb2CollectionHttpMessageConverter提供了一个出色的示例,用于将对象的集合转换为所需的内容类型。 需要牢记以下几点:

  1. 可以使boolean canRead(Class<?>, MediaType)方法始终返回false因为CSV内容是对象的集合,因此无法将其读取为类型指定的单个对象。
  2. boolean canRead(Type, Class<?>, MediaType)方法应检查Type以确保它指定Collection类型,并且还指定了期望该collection保留的元素类型。
  3. 应该实现T read(Type, Class<?>, HttpInputMessage)方法来读取CSV内容。
  4. 应该实现void write(T, Type, Class<?>, HttpInputMessage)方法来写入CSV内容。

步骤3 :CSV消息转换器应在配置中注册

@Override
protected void configureMessageConverters(final List<HttpMessageConverter<?>> converters)
{
  converters.add(csvMessageConverter());

  super.addDefaultHttpMessageConverters(converters);
}

步骤4 :应使用控制器方法来返回所需对象的集合

public List<?> get() { ... }

Github上有一个示例应用程序显示了这一功能。 启动应用程序,然后将请求发送到http://localhost:8080/persons.csvhttp://localhost:8080/persons.json分别检索CSV或JSON格式的数据。

有多种方法可以转换为CSV,但一种方法

    @RequestMapping(value = "/eblnotif/exportMailId", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody String exportMailIdCsv(@RequestBody Filters filters) throws IllegalAccessException,
        IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, IOException {

    List<EblNotif> eblnotif_list = accountSservice.exportMailIdCsv(filters);

    String separator = ";";
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    StringBuilder sb = new StringBuilder();
    sb.append("formName;mode;language;sendingDate;gpart;email;mailId").append(System.lineSeparator());
    for (EblNotif eblNotif : eblnotif_list) {
        sb.append(eblNotif.getFormName()).append(separator);
        sb.append(eblNotif.getMode()).append(separator);
        sb.append(eblNotif.getLanguage()).append(separator);
        sb.append(dateFormat.format(eblNotif.getSendingDate())).append(separator);
        sb.append(eblNotif.getGpart()).append(separator);
        sb.append(eblNotif.getEmail()).append(separator);
        sb.append(eblNotif.getMailId()).append(separator);
        sb.append(System.lineSeparator());
    }
    return sb.toString();
}

使用Apache Commons CSV,您可以执行以下操作:

 @RequestMapping(value = "/download/eblnotif")
    public void download(@RequestBody @Valid Filters filter,
                         HttpServletResponse httpServletResponse) throws Exception {
        List<EblNotifResource> resources = //find from the fitler 
        CSVPrinter csvPrinter = CSVWriterUtil.transformResourcesToCSVPrinter(new BufferedWriter(httpServletResponse.getWriter()), resources);
        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=\"file.csv\"");
        csvPrinter.flush();
        csvPrinter.close();
    }


    public final class CSVWriterUtil {

    private static final String NEW_LINE_SEPARATOR = "\n";

    private CSVWriterUtil() {
    }

    public static CSVPrinter transformResourcesToCSVPrinter(Writer writer, List<EblNotifResource> eblNotifResources) {
        try {
            CSVPrinter csvPrinter = new CSVPrinter(new BufferedWriter(writer), CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR));
            for (EblNotifResource eblNotifResource : eblNotifResources) {
                List<String> dataRecords = new ArrayList<>();
                dataRecords.add(eblNotifResource.getFormName());
                dataRecords.add(eblNotifResource.getSendingDate());
                //...etc 
                csvPrinter.printRecord(dataRecords);
            }
            return csvPrinter;
        } catch (IOException e) {
            throw new SystemException("Exception occurred while converting file", e);
        }
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM