Как использовать JasperReports с Spring MVC?
Я исследовал использование JasperReports (6.0.0) с Spring MVC (4.1.3) для создания отчетов в формате PDF. Spring изобилует" специфичными для Spring " способами интеграции с JasperReports для создания PDF-файлов:
- Использование
JasperReportsPdfView
полагается на устаревшие функции JasperReport - Использование
JasperReportsMultiFormatView
- Использование
JasperReportsViewResolver
Я изо всех сил пытался найти хорошие, полные примеры в интернете и хотел поделиться своими находками (см. мой ответ ниже ).
Не стесняйтесь добавлять дополнительные методы и / или улучшения, связанные с "как я могу интегрировать JasperReports с Spring4"?
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 @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 view resolver для сопоставления логических имен представлений с представлениями 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); }
Мне нравится такой подход. Контроллеры остаются "немыми" и имеют дело только со строковыми значениями, А отображение имен в представления может происходить все в одном местоположение.
Метод 4: Используйте JasperReportsViewResolver
Сконфигурируйте нулевой порядок
JasperReportViewResolver
, и трюк заключается в том, чтобы использоватьsetViewNames
, чтобы сказать Spring, с какими логическими именами представлений вы хотите иметь дело с этим решателем (в противном случае вы получите "не удалось загрузить отчет JasperReports из класса path resource [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; }
И внутри контроллера:
Это мой предпочтительный подход. Контроллеры разрешают Джаспер сообщает в очень аналогично тому, как представления jsp разрешаются с помощью@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; }
InternalResourceViewResolver
, и поэтому нет необходимости в явном файле сопоставления, как при подходе xml или файла свойств в методе #3 выше.EDIT
The javadocs for
JasperReportsPdfView
упомяните, что он использует устаревший APIJRExporter
. Есть ли лучший (более новый) вид JasperReports для использования? Возможно, выбор в пользуJasperReportsMultiFormatView
это лучший вариант, так как он, по-видимому, не используетсяJRExporter
.