原文: http://zetcode.com/articles/jasperspringbootweb/

在本教程中,我们展示如何在 Spring Boot 框架中使用 JasperReports。 我们创建一个 Web 应用。

JasperReports 是一个 Java 开源报告库。 它可以创建各种格式的报告,包括 PDF,HTML,XLS 或 CSV。 JasperReports 以一种简单而灵活的方式创建了面向页面的可打印文档。

JdbcTemplate是一个 Spring 库,可以帮助程序员创建与关系数据库和 JDBC 一起使用的应用。 它会处理许多繁琐且容易出错的底层细节,例如处理事务,清理资源以及正确处理异常。 JdbcTemplate在 Spring 的spring-jdbc模块中提供。

Spring 是用于开发 Java 企业应用的 Java 应用框架。 它还有助于集成各种企业组件。 Spring Boot 使创建具有 Spring 动力的生产级应用和服务变得很容易,而对安装的要求却最低。

Apache Derby 是完全用 Java 实现的开源关系数据库。 它占地面积小,易于部署和安装。 它可以在嵌入式和客户端/服务器模式下运行。

CARS

我们使用下表:

cars.sql

  1. -- SQL for the CARS table
  2. CREATE TABLE CARS(ID BIGINT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY
  3. (START WITH 1, INCREMENT BY 1), NAME VARCHAR(30), PRICE INT);
  4. INSERT INTO CARS(Name, Price) VALUES('Audi', 52642);
  5. INSERT INTO CARS(Name, Price) VALUES('Mercedes', 57127);
  6. INSERT INTO CARS(Name, Price) VALUES('Skoda', 9000);
  7. INSERT INTO CARS(Name, Price) VALUES('Volvo', 29000);
  8. INSERT INTO CARS(Name, Price) VALUES('Bentley', 350000);
  9. INSERT INTO CARS(Name, Price) VALUES('Citroen', 21000);
  10. INSERT INTO CARS(Name, Price) VALUES('Hummer', 41400);
  11. INSERT INTO CARS(Name, Price) VALUES('Volkswagen', 21600);

cars.sql文件创建CARS表。

  1. $ $DERBY_HOME/bin/ij
  2. ij version 10.11
  3. ij> CONNECT 'jdbc:derby:testdb';
  4. ij> RUN 'cars.sql';

一种选择是使用ij工具从 SQL 脚本创建表。 请参考 Apache Derby 教程以熟悉 Derby。

  1. $ $DERBY_HOME/bin/NetworkServerControl start &

使用NetworkServerControl工具启动 Derby 服务器。

应用

以下 Spring Boot 应用从数据库表加载数据,并使用 JasperReports 库从中生成 PDF 报告。 该应用与嵌入式 Tomcat 服务器一起运行。

  1. $ tree
  2. .
  3. ├── pom.xml
  4. └── src
  5. ├── main
  6. ├── java
  7. └── com
  8. └── zetcode
  9. ├── Application.java
  10. ├── bean
  11. └── Car.java
  12. ├── conf
  13. ├── AppConfig.java
  14. └── MvcConf.java
  15. ├── controller
  16. └── MyController.java
  17. └── service
  18. ├── CarService.java
  19. └── ICarService.java
  20. └── resources
  21. ├── application.yml
  22. ├── report2.jrxml
  23. └── static
  24. └── index.html
  25. └── test
  26. └── java

这是项目结构。

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  5. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  6. <modelVersion>4.0.0</modelVersion>
  7. <groupId>com.zetcode</groupId>
  8. <artifactId>JasperSpringBootWeb</artifactId>
  9. <version>1.0-SNAPSHOT</version>
  10. <packaging>war</packaging>
  11. <properties>
  12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  13. <maven.compiler.source>1.8</maven.compiler.source>
  14. <maven.compiler.target>1.8</maven.compiler.target>
  15. </properties>
  16. <parent>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-parent</artifactId>
  19. <version>1.5.2.RELEASE</version>
  20. </parent>
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.apache.derby</groupId>
  24. <artifactId>derbyclient</artifactId>
  25. <version>10.13.1.1</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>net.sf.jasperreports</groupId>
  29. <artifactId>jasperreports</artifactId>
  30. <version>6.4.0</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework</groupId>
  34. <artifactId>spring-context-support</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-web</artifactId>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.springframework.boot</groupId>
  42. <artifactId>spring-boot-starter-jdbc</artifactId>
  43. </dependency>
  44. </dependencies>
  45. <build>
  46. <plugins>
  47. <plugin>
  48. <groupId>org.springframework.boot</groupId>
  49. <artifactId>spring-boot-maven-plugin</artifactId>
  50. </plugin>
  51. </plugins>
  52. </build>
  53. </project>

Maven pom.xml文件包含 JasperReports 库,Derby 驱动程序和 Spring Boot 的依赖项。

report2.xml

  1. <?xml version = "1.0" encoding = "UTF-8"?>
  2. <!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
  3. "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
  4. <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports
  7. http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
  8. name="report2" pageWidth="595" pageHeight="842"
  9. columnWidth="555" leftMargin="20" rightMargin="20"
  10. topMargin="20" bottomMargin="20">
  11. <field name="Id" class="java.lang.Long">
  12. <fieldDescription><![CDATA[id]]></fieldDescription>
  13. </field>
  14. <field name="Name" class="java.lang.String">
  15. <fieldDescription><![CDATA[name]]></fieldDescription>
  16. </field>
  17. <field name="Price" class="java.lang.Integer">
  18. <fieldDescription><![CDATA[price]]></fieldDescription>
  19. </field>
  20. <detail>
  21. <band height="15">
  22. <textField>
  23. <reportElement x="0" y="0" width="50" height="15" />
  24. <textElement textAlignment="Right" verticalAlignment="Middle"/>
  25. <textFieldExpression class="java.lang.Long">
  26. <![CDATA[$F{Id}]]>
  27. </textFieldExpression>
  28. </textField>
  29. <textField>
  30. <reportElement x="150" y="0" width="100" height="15" />
  31. <textElement textAlignment="Left" verticalAlignment="Middle"/>
  32. <textFieldExpression class="java.lang.String">
  33. <![CDATA[$F{Name}]]>
  34. </textFieldExpression>
  35. </textField>
  36. <textField>
  37. <reportElement x="200" y="0" width="100" height="15"/>
  38. <textElement textAlignment="Right" verticalAlignment="Middle"/>
  39. <textFieldExpression class="java.lang.Integer">
  40. <![CDATA[$F{Price}]]>
  41. </textFieldExpression>
  42. </textField>
  43. </band>
  44. </detail>
  45. </jasperReport>

这是报告模板文件。 它位于src/main/resources目录中。 模板仅包含明细带。 在详细信息区域内,将对数据源提供的每个记录重复每个元素。

  1. <field name="Id" class="java.lang.Long">
  2. <fieldDescription><![CDATA[id]]></fieldDescription>
  3. </field>
  4. <field name="Name" class="java.lang.String">
  5. <fieldDescription><![CDATA[name]]></fieldDescription>
  6. </field>
  7. <field name="Price" class="java.lang.Integer">
  8. <fieldDescription><![CDATA[price]]></fieldDescription>
  9. </field>

报告中有三个字段。 这些字段映射到数据源 bean 的元素。

  1. <textField>
  2. <reportElement x="0" y="0" width="50" height="15" />
  3. <textElement textAlignment="Right" verticalAlignment="Middle"/>
  4. <textFieldExpression class="java.lang.Long">
  5. <![CDATA[$F{Id}]]>
  6. </textFieldExpression>
  7. </textField>

文本字段是充满动态数据的元素。 我们将一个字段中的值放在文本字段中。 我们使用$F{}语法引用该变量。

Car.java

  1. package com.zetcode.bean;
  2. public class Car {
  3. private Long id;
  4. private String name;
  5. private int price;
  6. public Car() {}
  7. public Car(Long id, String name, int price) {
  8. this.id = id;
  9. this.name = name;
  10. this.price = price;
  11. }
  12. public Long getId() {
  13. return id;
  14. }
  15. public void setId(Long id) {
  16. this.id = id;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public int getPrice() {
  25. return price;
  26. }
  27. public void setPrice(int price) {
  28. this.price = price;
  29. }
  30. @Override
  31. public String toString() {
  32. return "Car{" + "id=" + id + ", name=" + name + ", price=" + price + '}';
  33. }
  34. }

这是Car bean 类。 它包含商品 ID,名称和价格。

application.yml

  1. datasource:
  2. url: jdbc:derby://localhost:1527/testdb
  3. username: app
  4. password: app
  5. driverClassName: org.apache.derby.jdbc.ClientDriver

application.yml是主要的 Spring Boot 配置文件。 它包含 Derby 数据源。

AppConfig.java

  1. package com.zetcode.conf;
  2. import javax.sql.DataSource;
  3. import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
  4. import org.springframework.boot.context.properties.ConfigurationProperties;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. import org.springframework.context.annotation.Primary;
  8. @Configuration
  9. public class AppConfig {
  10. @Bean
  11. @Primary
  12. @ConfigurationProperties(prefix = "datasource")
  13. public DataSource primaryDataSource() {
  14. return DataSourceBuilder.create().build();
  15. }
  16. }

AppConfig是 Java 配置类。 它从配置文件创建数据源 bean。

MyController.java

  1. package com.zetcode.controller;
  2. import com.zetcode.service.ICarService;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.logging.Level;
  6. import java.util.logging.Logger;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.ui.Model;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RequestMethod;
  13. import org.springframework.web.servlet.ModelAndView;
  14. import org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView;
  15. @Controller
  16. public class MyController {
  17. @Autowired
  18. private ApplicationContext appContext;
  19. @Autowired
  20. private ICarService carService;
  21. @RequestMapping(path = "/pdf", method = RequestMethod.GET)
  22. public ModelAndView report() {
  23. JasperReportsPdfView view = new JasperReportsPdfView();
  24. view.setUrl("classpath:report2.jrxml");
  25. view.setApplicationContext(appContext);
  26. Map<String, Object> params = new HashMap<>();
  27. params.put("datasource", carService.findAll());
  28. return new ModelAndView(view, params);
  29. }
  30. }

MyController中,我们有两种方法可以响应两个请求。

  1. @Autowired
  2. private ICarService carService;

我们将CarService对象注入到属性中。 服务对象用于从数据库检索数据。

  1. @RequestMapping(path = "/pdf", method = RequestMethod.GET)
  2. public ModelAndView report() {
  3. JasperReportsPdfView view = new JasperReportsPdfView();
  4. view.setUrl("classpath:report2.jrxml");
  5. view.setApplicationContext(appContext);
  6. Map<String, Object> params = new HashMap<>();
  7. params.put("datasource", carService.getCars());
  8. return new ModelAndView(view, params);
  9. }

report()方法中,将生成报告并将其发送回客户端。 JasperReportsPdfView是 Spring 类,可从提供的模板和数据生成 PDF 报告。

ICarService.java

  1. package com.zetcode.service;
  2. import com.zetcode.bean.Car;
  3. import java.util.List;
  4. public interface ICarService {
  5. public List<Car> findAll();
  6. }

ICarService提供了一种从数据源获取所有汽车的契约方法。

CarService.java

  1. package com.zetcode.service;
  2. import com.zetcode.bean.Car;
  3. import java.util.List;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.jdbc.core.BeanPropertyRowMapper;
  6. import org.springframework.jdbc.core.JdbcTemplate;
  7. import org.springframework.stereotype.Service;
  8. @Service
  9. public class CarService implements ICarService {
  10. @Autowired
  11. private JdbcTemplate jtm;
  12. @Override
  13. public List<Car> findAll() {
  14. String sql = "SELECT * FROM Cars";
  15. List<Car> cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class));
  16. return cars;
  17. }
  18. }

CarService包含findAll()方法的实现。 我们借助JdbcTemplateCARS表中检索所有汽车。

  1. @Autowired
  2. private JdbcTemplate jtm;

注入JdbcTemplate

  1. String sql = "SELECT * FROM Cars";

这是要执行的 SQL。 我们从CARS表中选择所有汽车。

  1. List<Car> cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class));

BeanPropertyRowMapper将一行转换为指定映射目标类的新实例。

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Home Page</title>
  6. </head>
  7. <body>
  8. <a href="/pdf.html">Generate report</a>
  9. </body>
  10. </html>

index.html文件包含一个生成 PDF 报告的链接。

Application.java

  1. package com.zetcode;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
  4. @SpringBootApplication
  5. public class Application {
  6. public static void main(String[] args) {
  7. SpringApplication.run(Application.class, args);
  8. }
  9. }

Application设置 Spring Boot 应用。

在本教程中,我们使用 JasperReports 创建了 PDF 报告。 该应用使用 Spring Boot 框架,并在 Web 环境中运行。 您可能也对这些相关教程感兴趣: Spring Boot JasperReports CMD 集成使用 JasperReports API 创建报告使用 JasperReports 从 CSV 创建报告。 Java 教程