Ответ 1
Основываясь на моих исследованиях, я нашел следующие методы использования. Методы начинаются с самого прямого (наивного) подхода, включающего меньшую сложность/конфигурацию переднего плана и развиваться, чтобы стать более абстрактными, но с большим количеством зависимостей от конфигурации Spring/более сложной Spring.
Способ 1. Используйте API JasperReports непосредственно в контроллере
Просто запишите содержимое в выходной поток сервлета.
@RequestMapping(value = "helloReport1", method = RequestMethod.GET)
@ResponseBody
public void getRpt1(HttpServletResponse response) throws JRException, IOException {
InputStream jasperStream = this.getClass().getResourceAsStream("/jasperreports/HelloWorld1.jasper");
Map<String,Object> params = new HashMap<>();
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(jasperStream);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource());
response.setContentType("application/x-pdf");
response.setHeader("Content-disposition", "inline; filename=helloWorldReport.pdf");
final OutputStream outStream = response.getOutputStream();
JasperExportManager.exportReportToPdfStream(jasperPrint, outStream);
}
Способ 2: Ввод JasperReportPdf Просмотр в контроллер
Учитывая JasperReportsPdfView bean:
@Bean @Qualifier("helloWorldReport2")
public JasperReportsPdfView getHelloWorldReport() {
JasperReportsPdfView v = new JasperReportsPdfView();
v.setUrl("classpath:jasperreports/HelloWorld2.jasper");
v.setReportDataKey("datasource");
return v;
}
Это представление может быть введено или подключено к контроллеру для использования:
@Autowired @Qualifier("helloWorldReport2")
private JasperReportsPdfView helloReport;
@RequestMapping(value = "helloReport2", method = RequestMethod.GET)
public ModelAndView getRpt2(ModelAndView modelAndView) {
Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("datasource", new JREmptyDataSource());
modelAndView = new ModelAndView(helloReport, parameterMap);
return modelAndView;
}
Обратите внимание, что использование JasperReportsPdfView
(или более универсального JasperReportsMultiFormatView
) требует зависимости от spring -context-support:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.3</version>
</dependency>
Способ 3: использовать XML или ResourceBundle для преобразования имен объектов в представления JasperReport
Настройте новый распознаватель вида, в этом случае ResourceBundleViewResolver
запускается до InternalResourceViewResolver
. Это основано на заданных значениях порядка (0 происходит до 1):
@Bean
public ResourceBundleViewResolver getResourceBundleViewResolver() {
ResourceBundleViewResolver resolver = new ResourceBundleViewResolver();
resolver.setBasename("jasperreport-views");
resolver.setOrder(0);
return resolver;
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setOrder(1);
return resolver;
}
Затем в корне нашей траектории пути файл jasperreport-views.properties
может содержать имя логического представления, сопряженное с значениями класса и свойства (т.е. url и reportDataKey), имеющими отношение к разрыву JasperReport:
helloReport3.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
helloReport3.url=classpath:/jasperreports/HelloWorld3.jasper
helloReport3.reportDataKey=myDataSourceKey
Код контроллера выглядит следующим образом:
@RequestMapping(value = "helloReport3", method = RequestMethod.GET)
public ModelAndView getRpt3(ModelMap modelMap, ModelAndView modelAndView) {
modelMap.put("myDataSourceKey", new JREmptyDataSource());
return new ModelAndView("helloReport3", modelMap);
}
Мне нравится этот подход. Контроллеры остаются "тупыми" и имеют дело только со значениями String, и отображение имен в представления может происходить в одном месте.
Способ 4: Использовать JasperReportsViewResolver
Настройте нулевое упорядочение JasperReportViewResolver
, и трюк использует setViewNames
, чтобы сообщить Spring, какие имена логических представлений вы хотите обработать с помощью этого преобразователя (в противном случае вы закончите с "Не удалось загрузить отчет JasperReports из пути к классу ресурс [jasperreports/index.jasper]" ):
@Bean
public JasperReportsViewResolver getJasperReportsViewResolver() {
JasperReportsViewResolver resolver = new JasperReportsViewResolver();
resolver.setPrefix("classpath:/jasperreports/");
resolver.setSuffix(".jasper");
resolver.setReportDataKey("datasource");
resolver.setViewNames("rpt_*");
resolver.setViewClass(JasperReportsMultiFormatView.class);
resolver.setOrder(0);
return resolver;
}
@Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setOrder(1);
return resolver;
}
И внутри контроллера:
@RequestMapping(value = "helloReport4", method = RequestMethod.GET)
public ModelAndView getRpt4(ModelMap modelMap, ModelAndView modelAndView) {
modelMap.put("datasource", getWidgets());
modelMap.put("format", "pdf");
modelAndView = new ModelAndView("rpt_HelloWorld", modelMap);
return modelAndView;
}
Это мой предпочтительный подход. Контроллеры разрешают отчеты jasper очень похожим образом на то, как представления jsp разрешаются с помощью InternalResourceViewResolver
, и поэтому нет необходимости в явном файле сопоставления, как в подходе xml или файла свойств в методе № 3 выше.
EDIT
javadocs для JasperReportsPdfView
упоминает, что использует устаревший API JRExporter
. Есть ли лучший (более новый) вид JasperReports для использования? Возможно, выбор JasperReportsMultiFormatView
- лучший вариант, поскольку он не используется JRExporter
.