Spring Web MVCのViewでPDFを生成して返す

Spring Web MVCのドキュメントを読んでいた所、ViewとしてPDFが使用できるらしい記述を見つけました。
これまでにPDFを動的生成したいと思うことが度々あったため、これを機に試してみました。

Spring Web MVC 公式リファレンス

Spring Web MVCの公式ドキュメントにおいて、PDF Viewについてはこちらに記載されています。

必要なライブラリ

OpenPDFのライブラリを使用するため、pom.xmlに以下のように記載します。
Maven Repositoryはこちらです。

		<dependency>
		    <groupId>com.github.librepdf</groupId>
		    <artifactId>openpdf</artifactId>
		    <version>1.3.11</version>
		</dependency>

なおiTextも使用できるようですが、Spring Web MVCのリファレンスには以下の記載があります。

You should use the latest versions of the underlying document-generation libraries, if possible. In particular, we strongly recommend OpenPDF (for example, OpenPDF 1.2.12) instead of the outdated original iText 2.1.7, since OpenPDF is actively maintained and fixes an important vulnerability for untrusted PDF content.

すなわち「iText2.1.7は推奨せず、アクティブにメンテされているOpenPDFを推奨」しているようです。
なぜiText2.1.7に言及されているのかは、おそらくiTextはバージョン2.1.7より上はライセンスがMPLからAGPLへ変更されているからでしょう。
iTextの最新バージョンで動くとしてもAGPLに注意する必要がありますし、2.1.7だと脆弱性のリスクを抱えることになります。

個人的には特段の理由がない限り、OpenPDFを使うほうが無難だと思います。

実装例

Spring BootのWeb starterをベースにしました。
PDF Viewを定義し、そのViewをController側で使用しています。

PDF Viewの実装例

PDFのViewはAbstractPdfViewを継承し、以下のように実装しました。
modelで受け取ったリスト形式のテキストをパラグラフとして表示する他、2×2のテーブルにテキストを入れて表示しています。

public class MyPdfView extends AbstractPdfView {

    protected void buildPdfDocument(Map<String, Object> model, Document doc, PdfWriter writer,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        List<String> words = (List<String>) model.get("wordList");
        for (String word : words) {
            doc.add(new Paragraph(word));
        }
        
        Table table = new Table(2, 2);
        table.addCell(new Paragraph("first cell"));
        table.addCell(new Paragraph("second cell"));
        table.addCell(new Paragraph("third cell"));
        table.addCell(new Paragraph("fourth cell"));
        
        doc.add(table);
    }
}

Controllerの実装例

Controllerは以下のように実装しました。 動的なデータを渡すような想定で、wordsにテキストデータを入れて渡しています。

@Controller
public class PdfController {
	
	@RequestMapping("/pdf")
	public MyPdfView pdf(MyPdfView mav) {
		List<String> words = new ArrayList<>();
		words.add("First word");
		words.add("Second word");
		mav.addStaticAttribute("wordList", words);
		return mav;
	}
}

# ModelAndViewの癖で、変数名をmavにしてしまった…

動作確認

実装したものをローカルで実行しhttp://localhost:8080/pdfへアクセスすると、こちらのPDFが生成・表示されました。
したがってControllerやViewで指定したテキストが動的に差し込まれ、PDFが生成されていることを確認できました。

生成されたPDF

サンプル

作成したサンプルのソースコードはGitHubに置いてあります。

まとめ

Spring Web MVCのViewに、PDF Viewを使う方法を試しました。
帳票類に対応したViewさえ定義すれば、簡単にPDFファイルとして返すことができることが分かりました。
ただし日本語は入力してもPDFで表示されなかったため、日本語を使うには別途フォントを指定するなどの対応が必要になりそうです。

Excelも同様に生成することができるようなので、こちらも別途試してみたいと思います。

関連記事


  1. Spring Web MVCのViewでExcelを生成して返す
  2. Spring Web MVCのAuto Configuration周辺のクラス図を描いてみた
  3. ModelMapperで1対1に対応しないフィールドのマッピング
  4. Spring Data JPAのgetOne()で遅延ロードエラー
  5. Javaでオブジェクト配列からフィールド配列を生成
  6. Spring Boot アノテーション集
  7. Javaサーブレットにおける部分URLやファイルパスの取得

comments powered by Disqus