[英]Return a JSON response as CSV file from spring-boot controller
[英]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步 :可選,但建議
使用OpenCSV , uniVocity或Smooks (僅CSV解析器)之類的CSV轉換庫在CSV之間進行對象轉換。 使用良好的庫將節省大量樣板代碼,還可用於擴展對其他格式的支持,例如制表符分隔的值(TSV)和固定寬度的列。
步驟2 :實現
GenericHttpMessageConverter
創建GenericHttpMessageConverter
的實現,以使用在步驟1中選擇的CSV轉換庫將對象與CSV相互轉換。此步驟有點棘手,因為HttpMessageConverter
通常用於將單個對象轉換為所需的內容類型,而CSV內容是對象的集合(每行代表一個對象)。 但是,Spring團隊在Jaxb2CollectionHttpMessageConverter
提供了一個出色的示例,用於將對象的集合轉換為所需的內容類型。 需要牢記以下幾點:
boolean canRead(Class<?>, MediaType)
方法始終返回false
因為CSV內容是對象的集合,因此無法將其讀取為類型指定的單個對象。 boolean canRead(Type, Class<?>, MediaType)
方法應檢查Type
以確保它指定Collection
類型,並且還指定了期望該collection保留的元素類型。 T read(Type, Class<?>, HttpInputMessage)
方法來讀取CSV內容。 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.csv
或http://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.