Java入門 / Web入門

【Java Web入門 #4】JSPを利用する|内部処理・デザインの分離とテンプレートエンジン

2024.12.27

前回までの記事では、サーブレットの実行結果をWebブラウザで表示する方法についてご説明しましたが、Javaのコード上でHTMLの文字列を生成すると、実際に表示されるまでどのようなデザインとなるかがわからず、開発効率も高くありません。

またデザインを変更したい場合は、Javaのソースコードから対象の箇所を探し出して修正しなければならず、メンテナンス性も非常に悪くなってしまいます。当記事では、内部処理とデザインを分離させる仕組みとしてのテンプレートエンジンの役割と、Javaの代表的なテンプレートエンジンであるJSPを利用した画面の表示方法について簡単にご説明します。

◆Java Web入門の過去記事はこちら
◆Java入門 記事一覧はこちら

テンプレートエンジンとは

テンプレートエンジンの役割

テンプレートエンジンとは、静的なコンテンツ(テンプレート)に動的な情報(データ)を組み合わせることで、動的なコンテンツを生成する仕組みです。

テンプレートに埋め込むための形式(データモデル)のデータを動的に作成することで、同じテンプレートで様々な情報を表示することができます。

また、デザインと内部処理を分離することができるため、画面の構成はテンプレートに、データの取得や更新などは内部処理のプログラムに分け、効率良くアプリケーションを開発できます。

テンプレートエンジンを使用するメリット

Webアプリケーションでは、例えばECサイトの商品検索結果や、商品の詳細画面など、同じデザインフォーマットで異なる情報を表示することが多くあります。

このような場合に、画面のデザインをテンプレートとして作成しておき、表示したいデータを差し込むことで、個別に多くの画面を作成する必要がなくなります。

また当サイトも含め多くのWebサイトでは、異なる画面であってもヘッダーやメニュー、サイドバーなど共通のパーツを利用して画面を構成しています。このように表示する項目をパーツ化して作成・利用できることもテンプレートエンジンを利用するメリットの1つです。


また、デザインとアプリケーションの内部処理を分離することで、デザイナーとプログラマーが分業を行うことで開発効率が上がったり、運用開始後のメンテナンス性が高まることが期待できます。例えばデザイン変更を行いたい場合にテンプレートだけ修正することで対応できたり、内部処理のコード量を減らすことで、バグ発生時の原因調査などを効率よく行うことができます。

Javaの主なテンプレートエンジン

JavaのWebアプリケーションで利用されている主なテンプレートエンジンとしては、以下のようなものが挙げられます。

JSP

JSP(JavaServer Pages)は、Java EE(現在はJakarta EE)の標準的なテンプレートエンジンです。HTML内にJavaコードを埋め込むことで、動的なWebページを生成できます。JSPはサーブレットと連携して動作させるほか、単独でJavaのプログラムとして動作することもできます。

JSPは、Java EEの初期から存在する技術であり、多くのJava Webアプリケーションで利用されてきました。Java EEがJakarta EEに移行した後に「Jakarta Server Pages」「Jakarta Pages」と名称が変わりましたが、現在も「JSP」という名称が広く使用されています。
Eclipse Foundation - Jakarta Pages(英語)

Velocity・FreeMarker

VelocityとFreeMarkerは、Javaベースのオープンソースのテンプレートエンジンです。どちらもWebアプリケーションのHTML生成や、メールテンプレート、レポート、設定ファイルなどの動的なコンテンツ生成に広く利用されています。

Velocityは、シンプルで直感的な構文が特徴で、特に小規模なプロジェクトや、素早くプロトタイプを作成したい場合に適しています。当初Apacheソフトウェア財団の「Jakartaプロジェクト」の一環として開発されましたが、現在は「The Apache Velocity Project」としてJakartaプロジェクトから独立しています。
The Apache Velocity Project 公式サイト(英語)

FreeMarkerもApacheソフトウェア財団が管理するテンプレートエンジンですが、Velocity とは異なり、当初から独立したプロジェクトとして開発されています。Velocityと比べてより多くの機能と柔軟性を備えたテンプレートエンジンで、複雑なロジックの実装にも対応できることもあり、大規模なWebアプリケーションや、高度なカスタマイズが必要な場合に適しています。
Apache FreeMarker 公式サイト(英語)

Thymeleaf

Thymeleafは、Javaベースのモダンなサーバーサイドテンプレートエンジンです。特にJavaのフレームワークの1つであるSpring Frameworkとの親和性が高く、近年利用されることが多くなっているテンプレートエンジンです。
Thymeleaf 公式サイト(英語)

HTMLタグ内に属性を追加する形でテンプレートを作成するため、Webブラウザ上で直接テンプレートのデザインが確認でき、HTMLの知識があれば比較的習得しやすい点も人気の理由です。Thymeleafの公式サイトは英語のウェブサイトですが、チュートリアルのドキュメントは日本語訳されたものが公開されています。
Thymeleaf チュートリアル(日本語)

JSPの利用

それでは、JavaのWebアプリケーションでは最もポピュラーなテンプレートエンジンであるJSPを利用して、Webブラウザに画面を表示させてみましょう。

JSPファイル

JSPファイルには静的なHTML要素に加え、スクリプトレット(<% ~ %>で囲まれた範囲)を用いてJavaのコードを記述して実行したり、EL式(${ ~ } で囲まれた範囲)を用いてJavaの式を記述することができます。

スクリプトレットはHTMLタグの外側の範囲や、ヘッダー、ボディの任意の場所に記述することができますが、if条件を利用してHTML要素の構成を壊してしまったり、ファイル内のJavaのコードが全体を通して実行できないような形にならないように注意する必要があります。

Java
<%@ page contentType="text/html; charset=UTF-8"%>
<%
  // htmlタグの外側
  String hello = ""; 
%>
<!DOCTYPE html>
<html>
<head>
<!-- ヘッダー部分 -->
<%
  // headの中 
  hello = "Hello JSP!";
%>
</head>
<body>
<!-- コンテンツ本体部分 -->
<%= hello %> <!-- 変数helloの値をHTML上に出力 -->
${param.name} <!-- EL式を用いてリクエストパラメーターnameの値をHTML上に出力 -->
</body>
</html>

JSPの実装例

作成したJSPファイルで生成される画面を表示する方法としては、「URLを指定して直接JSPファイルを呼び出す」「サーブレットを呼び出してJSPに連携する」といった方法があります。ここではこれらの方法でJSPを利用した画面を表示する手順を説明します。

JSPを直接呼び出す

一番簡単な方法として、Webブラウザ上でファイルへのパスを直接指定することで、JSPを呼び出して表示することができます。この場合、サーバーサイドで実行する処理については、スクリプトレットを利用して、JSPファイルにJavaのコードを記述する必要があります。
※ただし、この方法では結局デザインとJavaのコードを同じファイルに記述するため保守性が非常に低く、またセキュリティリスクも高くなってしまうため、実際のアプリケーション開発ではほとんど利用されません。あくまで学習用としてご利用ください。

直接アクセスするためのJSPファイルとして、前回の記事(#3 パラメーターの利用)で作成した税込価格計算の画面を、JSPファイル上に直接実装したものを作成してみましょう。

まず/src/main/webappにJSPファイル用のフォルダーを作成し(ここではフォルダ名を「jsp」としました)、右クリック >「新規」>「JSP ファイル」の順に選択して、jspファイルを作成します。


ここではファイル名を direct.jsp として作成しました。
作成したJSPファイルの内容は以下の通りとします。3行目~28行目に記述してスクリプトレットでパラメーターの取得と計算処理を行い、29行目以降のHTMLの中に計算結果を埋め込むようにしています。(40~42行目)

Java
<%@ page contentType="text/html; charset=UTF-8"%>
<% // メイン処理のスクリプトレット

	// リクエストパラメータを取得
	String priceStr = request.getParameter("price");
	String taxRateStr = request.getParameter("taxRate");
	
	// 文字列を数値に変換
	int price = 0;
	double taxRate = 0;
	String errMsg = null;
	boolean hasErr = false;
	
	try {
	    price = Integer.parseInt(priceStr);
	    taxRate = Double.parseDouble(taxRateStr);
	    
	} catch(Exception e) {
	    // 数値に変換失敗した場合はエラーメッセージを表示
	    price = 0;
	    taxRate = 0;
	    errMsg = "価格(price)と消費税率(taxRate)を数値で指定してください。";
	    hasErr = true;
	}
	// 税込金額を計算(小数点以下切り捨て)
	int taxIncludedPrice = (int) Math.floor(price * (1 + taxRate / 100));
%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>税込価格計算(JSP)</title>
</head>
<body>

<% if(hasErr){  %>
	<p style="color: red;"><%= errMsg %></p>
<% } %>
	<p>税抜価格:<%= price %></p>
	<p>消費税率:<%= taxRate %></p>
	<h2>税込価格は<%= taxIncludedPrice %>円です。</h2>
</body>
</html>

direct.jsp


Tomcatサーバーを起動して、上記のJSPファイルに直接アクセスしてみます。(URLはwebappに作成したフォルダ名/ファイル名となります)
クエリストリングでGETパラメーターを指定するのをお忘れなく!

サーブレットの処理結果をJSPで出力する

次に、Webブラウザからはサーブレットを呼び出したうえで、JSPで処理結果を表示させてみましょう。
下記のサーブレット(JspServlet.java)を作成し、サーブレットでの処理結果をJSPに連動させるために、サーブレットで行いたい処理を完了させた後に、「RequestDispatcher」というクラスを利用してリクエストをJSPへ転送させます。

Java
package site.knovus.example;

import java.io.IOException;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@WebServlet("/JspServlet")
public class JspServlet extends HttpServlet {

    protected void doGet(
            HttpServletRequest request, 
            HttpServletResponse response)
            throws ServletException, IOException {
    	
        // リクエストパラメータを取得
        String priceStr = request.getParameter("price");
        String taxRateStr = request.getParameter("taxRate");

        // 文字列を数値に変換
        int price = 0;
        double taxRate = 0;
        String errMsg = null;
        boolean hasErr = false;
        
        try {
            price = Integer.parseInt(priceStr);
            taxRate = Double.parseDouble(taxRateStr);
            
        } catch(Exception e) {
            // 数値に変換失敗した場合はエラーメッセージを表示
            price = 0;
            taxRate = 0;
            errMsg = "価格(price)と消費税率(taxRate)を数値で指定してください。";
            hasErr = true;
        }
        // 税込金額を計算(小数点以下切り捨て)
        int taxIncludedPrice = (int) Math.floor(price * (1 + taxRate / 100));
        
        // サーブレットの処理結果をJSPで取得できるように、
        // requestオブジェクトに格納しておく
        request.setAttribute("priceResult", price);
        request.setAttribute("taxRateResult", taxRate);
        request.setAttribute("totalResult", taxIncludedPrice);
        
        request.setAttribute("errMsg", errMsg);
        request.setAttribute("hasErr", hasErr);
        
        // リクエストのフォワード(転送)先を対象のJSPに設定する
        RequestDispatcher dispatcher = 
        		request.getRequestDispatcher("/jsp/destination.jsp");
        
        // リクエストをフォワードする
        dispatcher.forward(request, response);
    }
}

JspServlet.java


次に、サーブレットの実行結果を表示するためのJSPファイルを作成します。サーブレットからJSPへリクエストを転送させるために、上記のコードの54行目で指定しているフォルダ(/jsp)内、ファイル名(destination.jsp)として作成する必要があります。


destination.jsp のコードは下記の内容で作成してください。
10~12行目ではスクリプトレットでエラーメッセージを表示するかどうかを判定し、13~15行目では各項目に表示する値をEL式を用いて設定しています。

Java
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>税込価格計算(Servlet+JSP)</title>
</head>
<body>
<% if((boolean)request.getAttribute("hasErr")){  %>
	<p style="color: red;">${errMsg}</p>
<% } %>
	<p>税抜価格:${priceResult}</p>
	<p>消費税率:${taxRateResult}</p>
	<h2>税込価格は${totalResult}円です。</h2>
</body>
</html>

destination.jsp

上記のJSPファイルのコードのように、サーブレットがrequest(HttpServletRequest)にsetAttributeメソッドで属性として格納したデータを、getAttributeメソッドを用いて取り出したり、EL式を用いて${attr_name}と記述することで出力することができます。(attr_name の部分は、requestに格納した時に設定した名称です)


例えば、JspServlet.javaの45行目で「request.setAttribute("priceResult", price);」として格納した文字列は、destination.jspの13行目でEL式「${priceResult}」を用いて出力(※)しています。

※EL式で出力される文字列の内容について

setAttributeメソッドで設定できるデータの型はObject型なので、文字列以外でも全てのクラスが格納できますが、EL式で変数の値をそのまま出力する場合は、toStringメソッドで取得される文字列が表示されることに注意してください。

また、リテラル型の場合はラッパークラスのtoStringメソッドで取得される文字列が出力され、nullの場合は何も出力されません。


サーブレットとJSPを作成したら、サーバーを起動してサーブレットのURLにアクセスしてみましょう。
処理結果が埋め込まれて表示されているのがわかると思います。


エラーメッセージの出力欄は、サーブレットでチェックエラーとなっただけ表示されます。10~12行目のif条件のように、スクリプトレットをコンテンツを囲うように条件設定した場合、内側にあるコンテンツ(HTML)は条件に合致した場合のみ出力されます。

JSPでエラーが発生した場合

JSP内で構文エラーや、スクリプトレットの中で例外が発生した場合など、正常に処理ができなかった場合は、Webブラウザ上にサーブレットコンテナのエラー画面が表示されます。(但し、実際にシステムを公開する場合は、専用のエラー画面を準備して詳細な情報が見えないようにするのが一般的です)

下の画像はTomcatサーバーでエラーが発生した場合に表示される画面です。発生した例外の種類や、当該箇所のコードなどが表示されるため、単純なミスであればデバッグ実行などを行わなくてもコードを修正するための参考情報を確認することができます。

(エラー画面の例。例外の発生箇所と、発生した例外の詳細が確認できる)



今回はテンプレートエンジンの役割と、JSPの基礎的な利用方法について説明しました。ひとまずJSPファイルを用いてWebページを表示することまでは、あまり難しいことをしなくてもできたと思いますがいかがでしょうか。

次回以降の記事では、JSPで宣言しなくても利用できる変数(暗黙オブジェクト)や、表示などを制御するための標準タグ(JSTL)など、JSPを便利に使う方法についても説明していきますので、ぜひお試しください。

株式会社GSI 採用サイト

新しいこと、始めよう

あなたとともに歩を進めるWEBメディア

広告

広告