J'ai étudié l'utilisation de JasperReports (6.0.0) avec Spring MVC (4.1.3) pour générer des rapports PDF. Spring est en proie à des méthodes d'intégration "spécifiques à Spring" avec JasperReports dans générer des PDF:
JasperReportsPdfView
repose sur des fonctionnalités obsolètes de JasperReport JasperReportsMultiFormatView
JasperReportsViewResolver
J'ai eu du mal à trouver de bons exemples complets en ligne et je voulais partager mes découvertes (voir ma réponse ci-dessous ).
N'hésitez pas à ajouter des méthodes et/ou des améliorations supplémentaires liées à "Comment puis-je intégrer JasperReports avec Spring4"?
Sur la base de mes recherches, j'ai trouvé les méthodes d'utilisation suivantes. Les méthodes commencent par l'approche la plus directe (naïve) impliquant moins de complexité/configuration initiale et évoluent pour devenir plus abstraites, mais avec davantage de dépendances sur la configuration de Spring/plus complexe.
Il suffit d'écrire le contenu dans le flux de sortie de la servlet.
@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);
}
Étant donné le bean JasperReportsPdfView:
@Bean @Qualifier("helloWorldReport2")
public JasperReportsPdfView getHelloWorldReport() {
JasperReportsPdfView v = new JasperReportsPdfView();
v.setUrl("classpath:jasperreports/HelloWorld2.jasper");
v.setReportDataKey("datasource");
return v;
}
Cette vue peut être injectée ou câblée dans le contrôleur pour être utilisée:
@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;
}
Notez que l'utilisation de JasperReportsPdfView
(ou du plus polyvalent JasperReportsMultiFormatView
) nécessite une dépendance sur le support contextuel-ressort:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.3</version>
</dependency>
Configurez un nouveau résolveur de vue, dans ce cas le ResourceBundleViewResolver
à exécuter avant le InternalResourceViewResolver
. Ceci est basé sur les valeurs d’ordre définies (0 avant 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;
}
Ensuite, à la racine de notre chemin de classe, le fichier jasperreport-views.properties
Peut contenir le nom de la vue logique associé aux valeurs de classe et de propriété (c'est-à-dire url et reportDataKey) pertinentes pour le rendu d'un JasperReport:
helloReport3.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
helloReport3.url=classpath:/jasperreports/HelloWorld3.jasper
helloReport3.reportDataKey=myDataSourceKey
Le code du contrôleur ressemble à ceci:
@RequestMapping(value = "helloReport3", method = RequestMethod.GET)
public ModelAndView getRpt3(ModelMap modelMap, ModelAndView modelAndView) {
modelMap.put("myDataSourceKey", new JREmptyDataSource());
return new ModelAndView("helloReport3", modelMap);
}
J'aime cette approche. Les contrôleurs restent "muets" et ne traitent que les valeurs de chaîne. Le mappage des noms sur les vues peut se dérouler au même endroit.
Configurez un JasperReportViewResolver
zéro-commandé et l'astuce consiste à utiliser setViewNames
pour indiquer à Spring les noms de vues logiques que vous voulez que ce résolveur traite (sinon vous obtenez "Impossible de charger JasperReports report de la classe ressource de chemin [jasperreports/index.jasper] "erreurs de type):
@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;
}
Et à l'intérieur du contrôleur:
@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;
}
Ceci est mon approche préférée. Les contrôleurs résolvent les rapports jasper de manière très similaire à la façon dont les vues jsp sont résolues à l'aide de InternalResourceViewResolver
et il n'est donc pas nécessaire de créer un fichier de mappage explicite, contrairement à l'approche XML ou au fichier de propriétés de la méthode n ° 3 ci-dessus.
[~ # ~] éditer [~ # ~]
Le javadocs for JasperReportsPdfView
mentionne qu'il utilise l'API obsolète JRExporter
. Existe-t-il une meilleure vue (plus récente) de JasperReports à utiliser? Peut-être que l’option JasperReportsMultiFormatView
est une meilleure option car elle ne semble pas utiliser JRExporter
.