Spring BootでJasperReportsを使ってPDFを返却するAPIを作る方法
Spring Bootアプリケーションに JasperReports を組み合わせると、データを元にしたレポートを簡単に PDF や XML などの形式で出力できます。本記事では、商品価格の一覧を PDF として返却する REST API を作成する方法を解説します。JasperReports はプリンタや画面だけでなく、PDF、XLS、RTF、CSV、XML、HTML、ODT など多様な形式に出力できる Java 製のレポーティングツールで、Spring Boot と組み合わせることでダウンロード可能なレポート API を構築できます。
1. 概要
- 目的:商品価格一覧を PDF として返却する REST API を Spring Boot で構築する。
- 使用するツール/ライブラリ:
- Spring Boot
- JasperReports ライブラリ
- Jaspersoft Studio(レポートテンプレート作成用)
- アウトプット:
/item-price-report/pdfなどのエンドポイントにアクセスすると、商品名と価格を一覧にした PDF ファイルがダウンロードされます。
2. JasperReports の準備
2.1 依存関係の追加
Maven プロジェクトの場合、pom.xml に以下を追加します。最新バージョンは Maven Central で確認してください。Spring のロギング機構を利用するため、commons‑logging を除外しています。
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.20.5</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
2.2 テンプレート(JRXML)の作成
- Jaspersoft Studio(または iReport)をインストールして起動します。テンプレートは
.jrxml拡張子の XML ファイルで、Jaspersoft Studio で自由に設計できます。JasperReports はテンプレートをもとにデータをバインドしてレポートを生成します。レポートテンプレートの作成はこの記事の範囲外ですが、Jaspersoft Studio を使用して作成するのが一般的です。 - 今回は「商品名」と「価格」の 2 列を持つ簡単なテーブルを作成し、タイトルやサブタイトルも追加します。作成後、ファイルを
src/main/resources/reports/item-price-report.jrxmlとしてプロジェクトに保存します。
テンプレート設計時に以下のポイントを意識すると実装がスムーズです。
- フィールド定義:
$F{name}、$F{price}など、データソースの Java Bean のプロパティ名と一致させます。 - パラメータ:レポートタイトルなど動的に変更したい値は
$P{title}のようにパラメータとして定義し、プログラム側から Map で渡します。 - レイアウト:用紙サイズやマージン、列幅などを指定できます。サンプルの item-report.jrxml では report タイトルと item 列を定義しています。
3. サービス実装
以下に示す JasperReportService クラスは、JRXML テンプレートを読み込み、商品データを埋め込み、PDF バイト配列を返すサービスです。
3.1 テンプレートをコンパイルする
JasperReports は JRXML ファイルを コンパイル して JasperReport インスタンスに変換する必要があります。通常は起動時または初回リクエスト時にコンパイルし、パフォーマンスを向上させるために .jasper ファイルとして保存して再利用します。Spring の ResourceUtils を使うと classpath からテンプレートを読み込めます。コンパイル後は JRSaver.saveObject() で保存し、次回以降は JRLoader.loadObject() で読み込みます。
@Service
public class JasperReportService {
public byte[] generateItemPriceReport(List<Product> products) throws JRException, IOException {
// 既にコンパイル済みのレポートがあれば再利用
JasperReport jasperReport;
File compiledFile = ResourceUtils.getFile("classpath:reports/item-price-report.jasper");
if (compiledFile.exists()) {
jasperReport = (JasperReport) JRLoader.loadObject(compiledFile);
} else {
// JRXML を読み込みコンパイル
File file = ResourceUtils.getFile("classpath:reports/item-price-report.jrxml");
jasperReport = JasperCompileManager.compileReport(file.getAbsolutePath());
// コンパイル済みファイルを保存
JRSaver.saveObject(jasperReport, compiledFile.getAbsolutePath());
}
// パラメータ設定(レポートタイトルなど)
Map<String, Object> parameters = new HashMap<>();
parameters.put("title", "商品価格一覧");
// データソース設定:JRBeanCollectionDataSource に Java のリストを渡す
JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(products);
// レポートを埋め込み
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
// PDF にエクスポート
return JasperExportManager.exportReportToPdf(jasperPrint);
}
}
上記コードでは、商品を表す Product エンティティのリストを JRBeanCollectionDataSource に渡し、テンプレート内で $F{name}、$F{price} として参照できるようにしています。JasperFillManager.fillReport() はテンプレート、パラメータ、データソースを受け取り、埋め込み済みレポート (JasperPrint) を生成します。最終的に JasperExportManager.exportReportToPdf() を呼び出して PDF 形式のバイト配列に変換します。
ポイント:レポート生成は CPU・I/O 負荷の高い処理になりやすいので、必要に応じてジョブ化やキャッシュ、非同期処理を検討してください。
3.2 エンティティとリポジトリの例
以下は簡単な Product エンティティと Spring Data JPA リポジトリの例です。実際にはデータベース設計に応じてフィールドや型を変更してください。
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private BigDecimal price;
// getters and setters
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {}
4. コントローラ実装
Spring MVC の @RestController を使って PDF を返却するエンドポイントを定義します。生成された PDF バイト配列を ResponseEntity<byte[]> に包み、HTTP ヘッダーで Content-Type や Content-Disposition を設定します。
@RestController
@RequestMapping("/item-price-report")
public class ReportController {
private final ProductRepository productRepository;
private final JasperReportService jasperReportService;
public ReportController(ProductRepository productRepository, JasperReportService jasperReportService) {
this.productRepository = productRepository;
this.jasperReportService = jasperReportService;
}
@GetMapping("/pdf")
public ResponseEntity<byte[]> exportPdf() throws JRException, IOException {
// 商品データを取得(例ではすべて取得)
List<Product> products = productRepository.findAll();
byte[] pdfBytes = jasperReportService.generateItemPriceReport(products);
// HTTP レスポンスの設定
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "application/pdf; charset=UTF-8")
// ダウンロード時のファイル名を指定
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=item-price-report.pdf")
.body(pdfBytes);
}
}
上記のように、GET /item-price-report/pdf へアクセスすると Spring Boot が自動的に PDF ファイルをダウンロードさせます。レスポンスヘッダー Content-Disposition: attachment を inline に変更すると、ブラウザで直接表示させることも可能です。
5. 動作確認
- Spring Boot アプリケーションを起動します。
- ブラウザまたは Postman から
http://localhost:8080/item-price-report/pdfにアクセスします。データが存在すれば、商品名と価格を一覧にした PDF がダウンロードされるはずです。 - JRXML テンプレートを変更するとレポートのレイアウトや項目が変わるので、必要に応じてカラムを追加・削除してください。
6. まとめ
- JasperReports は Java アプリケーションから PDF などのレポートを生成できるライブラリで、Spring Boot と組み合わせることで REST API からレポートをダウンロードする機能が簡単に実現できます。
- テンプレート (
.jrxml) は Jaspersoft Studio などでデザインし、JasperCompileManager.compileReport()でコンパイルして使用します。 JRBeanCollectionDataSourceを使うと Java のリストをデータソースとして簡単に利用できます。- レポート生成は重い処理になる場合があるので、ジョブ化やキャッシュ、非同期処理を検討するとスケーラビリティが向上します。
この手順に従えば、商品価格一覧や他のドメインに応用した PDF 出力 API を簡単に実装できます。必要に応じてレポート形式(HTML、Excel など)を切り替えたい場合は、JasperExportManager.exportReportToXml() や JasperExportManager.exportReportToHtmlFile() などのメソッドを利用してください。
是非フォローしてください
最新の情報をお伝えします
