JSP + ZXing で Web サイトに QRCode を表示してみる簡単なサンプル


JSP サイトを管理している知り合いが「QRCode を表示したい」と言っていたので、週末にちょっと試してみました。

Java だと OSS (Apache License 2.0) の ZXing がよく使われているみたいなので、JSP Web サイトに組み込んだメモとなります。

実際の Web 画面

以下のような入力画面で QRCode に指定したいURLを入力して「Submit」すると

以下のように URL を QRCode に変換して表示します。「Back」で元ページに戻ります。

開発環境

今回利用した開発環境は素の Eclipse 2020-09 (4.17.0) の Java EE パースペクティブで、サーバーに Tomcat v8.5 を追加指定したものです.

赤枠が今回のために追加、作成したファイルになります。

WebContent/WEB-INF/lib には関連する jar ファイルをコピーしてあります。

ZXing リポジトリに jar が見当たらないので、MVN Repository の ZXing CoreZXing Java SE Extensions などから入手すると良いでしょう。

jaxb-api-2.3.1.jar は Java8 などの環境では必要ないかもしれません。エラーが出るようでしたら、やはり MVN Repository の JAXB API などから入手して配置してください。

実際のコード

入力ページ

入力ページは通常の html ページです。Bootstrap のテンプレート にフォーム要素を追加しただけの、非常にシンプルなものです。

WebContent/index.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Simple QR sample with JSP</title>
  </head>
  <body>

<div class="container">
    <h2>Simple QR sample with JSP</h2>
    <form action="/test01/QRCode.jsp"> <!-- 遷移先の JSP ページ -->
        <div class="form-group">
            <label for="i_url">Target URL</label>
            <input type="text" class="form-control" id="i_url" name="i_url">
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</div>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
  </body>
</html>

JSP ページ

さてこちらは、入力を受けて QRCode を生成している部分です。ZXing のサンプルを、そのまま JSP 化したので、素直なコードだと思います。

WebContent/QRCode.jsp
<%@ page import="com.google.zxing.qrcode.QRCodeWriter" %>
<%@ page import="com.google.zxing.common.BitMatrix" %>
<%@ page import="com.google.zxing.BarcodeFormat" %>
<%@ page import="com.google.zxing.client.j2se.MatrixToImageWriter" %>
<%@ page import="java.awt.image.BufferedImage" %>
<%@ page import="test01.BufferedImageUtil" %>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
    <title>Output of "Simple QR sample with JSP"</title>
</head>
<body>

<%
String i_url = request.getParameter("i_url");
QRCodeWriter qrWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrWriter.encode(i_url, BarcodeFormat.QR_CODE, 300, 300);
BufferedImage bImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
%>

<div class="container">
    <h2>Output of "Simple QR sample with JSP"</h2>
    <p>Target URL: <%= i_url %></p>
    <img src="<%= BufferedImageUtil.convert2DataURI(bImage, "png") %>"/>
    <form action="/test01/">
        <button type="submit" class="btn btn-primary">Back</button>
    </form>
</div>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>

BufferedImageUtil クラス

今回、ポイントとなるのは BufferedImageUtil クラスです。

ZXing の Java サンプルを探してみたのですが、いったんファイルに出力する例が多くヒットしました。しかし Web サービスの場合、できればテンポラリファイル作成は避けたいところです。

というわけで convert2DataURI という、BufferedImage オブジェクトから Data URI をダイレクトに生成する簡単な関数を用意してみました。

test01.BufferedImageUtil.java
package test01;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.xml.bind.DatatypeConverter;

public class BufferedImageUtil {
    public static String convert2DataURI(BufferedImage bi, String type) throws IOException {
        if (bi == null || type == null) {
            return ""; // TODO: Default error image
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(bi, type, baos);
        return "data:image/" + type + ";base64," + DatatypeConverter.printBase64Binary(baos.toByteArray());
    }
}

エラー処理をサボっています。実際に使う際には、エラー画像の Data URI をあらかじめ用意しておいて、問題発生時にはそれを返してあげるのも良いとおもいます。

ライセンス

この投稿に含まれる私の作成した全てのコードは Creative Commons Zero ライセンスとします。自由にお使いください。

Enjoy!

以上、JSP で作成した Web サイトに、QRCode 表示の実装を試してみました。これをベースに、いろいろ機能を追加して遊んでみてください。

ではまた!