前回は、JavaBeansについて学びました。

今回は、ELとJSTLについて学びます。

この章の内容は覚える必要はありませんが、後のシステム開発演習で参照できるようにブックマークしておいてください。

1. なぜ、ELが必要なのか?

EL(Expression Language)はすでに少し見たように変数やJavaBeansクラスのプロパティ値など、指定された式の出力を行うための言語です。ELを使えば型をそれほど意識しなくても済むようになり、デザイナーの方にJSPを扱ってもらいやすくなります。ELは日本語では式言語と呼ばれることもあります。

JSTLなどの拡張タグライブラリと用いれば、プログラムの知識が少ない人でも条件分岐や繰り返しを実現することができるようになります。

2. ELの基本

基本的なELはこれまでにも出てきましたので、ここでは簡単に振り返りたいと思います。

2.1 ELの記述方法

EL(Expression Language)とは、JSPの表示に関わる技術です。ELは、短いプログラムコードを記述することで式を評価したり、変数に値をセットしたり取り出したり、メソッドを実行できる技術でした。


JSP2.0より導入されています。
https://docs.oracle.com/javaee/6/tutorial/doc/bnahq.html


ELは以下の形で定義します。

ELの書式

${式}

この時、{}で囲まれた式を評価し、結果を表示します。

以下のel_basic.jspを読み込んで質問に答えてください。

${"Hello World"}
<br>
${'Hello World'}
<br>
${42 * 42}
<br>
I'm ${20 + 3} years old.
<br>
Hello World has ${"Hello World".length()} characters.
<br>
  • ELでは、文字列をシングルクォーテーション、ダブルクオーテーションどちらで囲みますか?
あなたの答え:
  • ELでは、数値を何で囲みますか?
あなたの答え:
  • ELを文字列の中に埋め込むことはできますか?
あなたの答え:
  • ELの中でメソッドを使うことはできますか?
あなたの答え:

このELの場合は文字列をシングルクォーテーションでも囲むことができるのはダブルクォーテーションの中に入れられるようにするためです。つまり、「"${bloodType == "A"}"」とすることはできませんが、「"${bloodType == 'A'}"」あるいは「'${bloodType == "A"}'」とすることはできるのです。また、詳述します。

3. ELの演算子

ここでは、ELで使う演算子を見ていきます。

ただし、JavaSEでも演算子は学びましたのでここではEL特有の部分だけを押さえてください。

3.1 ELの算術演算子

ELの算術演算子はJavaSEのときと同じと覚えてください。ただし、ELの場合は整数同士の割り算が実数になります。

ELの算術演算子をまとめると下表7.1のとおりです。

算術演算子演算内容式の例結果(値)
+足し算${1 + 2}3
-引き算${ 1 - 2 } -1
*掛け算${ 2 * 3 } 6
/割り算${ 5 / 2 } 2.5
%剰余(余りを求める)${ 5 % 2 } 1
表7.1 ELの算術演算子

以下の以下のel_arithmetic.jspはELの算術演算子の使用例です。

${1+2}
<br>
${1-2}
<br>
${2*3}
<br>
${5/2}
<br>
${5%2}
<br>
${"Hello"+=" World"}

3.2 ELの関係演算子

関係演算子もJavaSEと同様です。

ただし、ELには別表記があります。

別表記がある理由はHTMLの中に入れたときにも関係演算子を見やすくするため、とお考えください。

「<」よりも「lt」の方がHTMLのタグの中に入ったときに見やすいです。

ELの関係演算子をまとめると下表7.2のとおりです。

関係演算子 (別表記)説明式の例 (別表記) 結果(値)
== (eq)左辺と右辺が等しい${1 == 1} (1 eq 1)true
!= (ne) 左辺と右辺が等しくない${1 != 2 } (1 ne 1) true
> (gt) 左辺が右辺より大きい${ 1 > 2 } (1 gt 1) false
< (lt) 左辺が右辺より小さい${ 1 < 2 } (1 lt 1) true
>= (ge) 左辺が右辺以上である${ 1 >= 2 } (1 ge 1) false
<= (le) 左辺が右辺以下である${ 1 <= 2 } (1 le 1) true
emptynullまたは空文字である${empty ""}
${empty null}
true
表7.2 ELの関係演算子

ここではELの場合は==で文字列の比較ができることを知っておきましょう。(JavaSEではequalsメソッドを使う必要がありましたね)

なお、別表記の英語の意味は以下のとおりです。

eq:equal
ne:negate
gt:greater than
lt:less than
ge:greater than or equal to
le:less than or equal to

余裕があれば、覚えましょう。

他の言語でも使われる表現(例えばLinuxのシェルスクリプト)ですから覚えておいて損はありません。

以下のel_relational.jspはELにおける関係演算子の使用例です。

${1 == 1}
<br>
${1 != 2}
<br>
${1 > 2}
<br>
${1 < 2}
<br>
${1 >= 2}
<br>
${1 <= 2}
<hr>
${1 eq 1}
<br>
${1 ne 2}
<br>
${1 gt 2}
<br>
${1 lt 2}
<br>
${1 ge 2}
<br>
${1 le 2}
<br>
${empty ""}
<br>
${empty null}
<br>
${empty "Hello"}

3.3 ELの論理演算子

論理演算子も基本はJavaSEと同じです。ただしここでも別表記があります。

ELの論理演算子をまとめると下表7.3のとおりです。

演算子 (別表記)読み方式がtrueになる条件使用例 (別表記)
&& (and)かつ AND左辺と右辺の両方がtrue${1 eq 1 && 2 eq 1} (${1 eq 1 and 2 eq 1})
|| (or)または ORすくなくとも左辺と右辺のどちらかがtrue${1 eq 1 || 2 eq 1} (${1 eq 1 or 2 eq 1})
! (not) 否定 NOT条件式がfalse ${${!(1 eq 1)} (${not(1 eq 1)})
表7.3 ELの論理演算子

以下のel_logical.jspはELにおける論理演算子の使用例です。

${1 eq 1 && 2 eq 1}    
<br>
${1 eq 1 and 2 eq 1}
<br>
${1 eq 1 || 2 eq 1}    
<br>
${1 eq 1 or 2 eq 1}
<br>
${!(1 eq 1)}    
<br> 
${not(1 eq 1)} 

4. ELとJavaBeans

前章のJavaBeansとELは相性がいいです。

ELを使うと JavaBeansのプロパティを簡単に出力できます

ただし、その前に少し補足説明です。

このあとしばらくコード量を減らして見やすくするためにスクリプトレットを使います。

この章では、MVCパターンの原則を破ってスクリプトレットを使います。

理由は、見易さのためです。

サーブレットとJSPを使った本来のWebアプリケーションの書き方ですと以下WasteServlet.javaとsample.jspのようにファイルが2つに別れるうえにコード量も増えます。

package p07;

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

@WebServlet(name = "WasteServlet", urlPatterns = {"/WasteServlet"})
public class WasteServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("message", "Hello World");
        
        request.getRequestDispatcher("07JSTL/sample.jsp").forward(request, response);
    }
}
${message}

しかし、スクリプトレットを使えば上記の2つのファイルの記述が以下expression1.jspのようになります。ファイルが1つにまとめられる上にコード量が減って見易くなったのがお分かりになりますか?

<%
 request.setAttribute("message", "Hello World");
%>

${message}

よって、この章のみスクリプトレットを使うことをご了承ください。

リクエスト属性に入っているJavaBeansのデータをELで表示する

さて、JavaBeansをリクエスト属性に入れて、ELで取り出す方法を以下el_bean1.jspで見てみましょう。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="p06.CustomerBean"%>
<%
    CustomerBean cb1 = new CustomerBean();
    cb1.setCustomerId(1);
    cb1.setName("今井");
    request.setAttribute("customer1", cb1);
    CustomerBean cb2 = new CustomerBean();
    request.setAttribute("customer2", cb2);
%>

${customer1}
<br>
${customer1.getName()}
<br>
${customer1.name}
<hr>
${customer2.name}
  • 16行目のようにリクエスト属性名を指定すると何が出力されますか?
あなたの答え:
  • 18行目のように属性名に続けてメソッドを呼び出すとどうなりますか?
あなたの答え:
  • 20行目のように属性名に続けてプロパティを呼び出すとどうなりますか?
あなたの答え:
  • 22行目のようにnullのオブジェクトをELに入れるとどうなりますか?
あなたの答え:

このように、nullのオブジェクトをELに入れると何も出力されません。(NullPointerExceptionは発生しません)JavaSEを学んできた皆さんのようなエンジニアには違和感の残る仕様かもしれません。しかし、JSPが表示を担当している点、JSPを扱うのがデザイナーさんである点を考えると納得できる仕様です。うまく活用してください。

調べてみましょう

先程のexpression1.jspにはrequestという変数が宣言もなく使用されていました。これはJSPの暗黙オブジェクト【implicit objects】と呼ばれるものです。余裕があればこの暗黙オブジェクトについて調べなさい。

調べたことのメモ:

JavaBeansの入れ子の例

次にBeanの中にBeanが入っている例、Beanの入れ子の例を以下のel_bean2.jspで見てみましょう。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@page import="p06.CustomersBean"%>
<%@page import="p06.CustomerBean"%>
<%
    CustomerBean cb1 = new CustomerBean();
    cb1.setCustomerId(1);
    cb1.setName("今井");
    CustomerBean cb2 = new CustomerBean();
    cb2.setCustomerId(2);
    cb2.setName("田渕");
    
    CustomersBean csb = new CustomersBean();
    csb.addCustomer(cb1);
    csb.addCustomer(cb2);
    request.setAttribute("customers", csb);
%>

${customers}
<br>
${customers.getCustomerArrayList()}
<br>
${customers.customerArrayList}
<br>
${customers.customerArrayList[0].name}
<br>
  • 22行目のようにBeanの入ったBeanを指定すると何が出力されますか?
あなたの答え:
  • 24行目のようにBeanのメソッドを呼び出すと何が出力されますか?
あなたの答え:
  • 26行目のようにBeanのプロパティを呼び出すと何が出力されますか?
あなたの答え:
  • 28行目のようにBeanのプロパティの0番目のプロパティを呼び出すことはできますか?
あなたの答え:

このようにしてBeanのプロパティのプロパティにアクセスすることも可能です。しかし、実際には Beanのプロパティのプロパティにアクセスする場合には次のJSTLの繰り返しを使います。この点はまたあとで詳述します。

実験1

ELとコメントの関係

コメントだけからなる以下のcomment.jsp を実行するとどうなるでしょうか?HTMLのソースまで見て確かめてみましょう。

<%@page contentType="text/html" pageEncoding="UTF-8"%>

        <!-- htmlのコメント  ${1 +2 } -->
        <%-- JSPのコメント ${1 +2 } --%>
実験結果のメモ:

5. ELを記述できる場所

ELは文字列として評価されますのでHTMLファイルで文字列が書けるところであれば、どこでも書くことができます。例えば、以下elAndHTML.jspのようにHTMLのタグにもタグの属性値にも入れられます。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>elAndHTML.jsp</title>
    </head>
    <body>
        <%
            request.setAttribute("message", "Hello World");
            request.setAttribute("tag", "h2");
        %>
        <input type="text" value="${message}">
        
        <${tag}>メッセージ</${tag}>
        
    </body>
</html>

また、例えば以下elAndJavaScript.jspのようにJavaScriptの中にも書くことができます。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>ELはJavaScriptの中にも書けます</title>
    </head>
    <body>
        <%
            request.setAttribute("message", "Hello World");
        %>
        <script>
            window.onload = function () {
                alert("${message}");
            };
        </script>
    </body>
</html>

6. JSTLとは何か?

JSTL【JSP Standard Tag Library】はその名の通り、JSP内でよく使われる機能をライブラリ【Library】= 図書館としてまとめたものです。先のELと組み合わせることで、スクリプトレットが不要になり、可読性・保守性が向上します。

JSTLはカスタムタグといって自分でタグを作るのともできます。しかし、本新人研修では既に用意されているタグのみを使います。しかもJSTLのうち2つ、Coreタグという核となる基本のタグとi18nタグ【Internationalization】(面白いネーミングですね)という表示形式に関わるタグのみ紹介します。(本来 Internationalizationのタグは国際化に関するJSTLタグですが、本研修では表示形式を整える目的でのみ使用します。)

7. JSTLの使い方

当社新人エンジニア研修の環境では、JSPの1行目に以下のようにしてPrefixとURIを指定するだけでJSTLが使えるようになります。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

※Coreタグの例

7.1 JSTLのCoreタグの使い方

JSTLの Coreタグ を使って条件分岐と繰り返しができるようになりましょう。

なお、以前出てきた以下の2つのタグ

<c:out> 値を安全に出力する
<c:redirect> リダイレクトする

とその他の使用頻度が低めのコアタグについては説明を割愛していますのでご了承ください。

なお、 Coreタグは全て <c:タグの種類> のように書きます。

7.2 条件分岐

<c:if>

JSTLで単純分岐を実現するには<c:if>タグを使います

<c:if>の書式

<c:if test = "判定条件">

真の場合の処理(例えば、HTMLを書けば出力がなされる:以降同様)

</c:if>

HTMLと同じように開始終了タグでifのブロックを表現します。

私達は当たり前のようにJavaSEでブロックを表現するのに{}を使ってきました。しかし、JSTLのようにブロックの開始と終了を何らかの単語で表現するプログラミング言語もたくさんあるのですね。今のうちに慣れておきましょう。

<c:if> のtest属性には判定条件をEL式を使って記述します。

JavaSEで書かれた以下JavaSESampleIf.javaのような処理があるとします。

package p07;

public class JavaSESampleIf {

    public static void main(String[] args) {

        if (true) {
            System.out.println(true);
        }

        if (1 < 2) {
            System.out.println(true);
        }

        if (1 > 2) {
            System.out.println(true);
        }
    }
}

以下if1.jspは同じ処理をJSPで実現したものです。

読み込んで質問に答えてください。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>if1</title>
    <body>
        <c:if test="${true}" >
            trueです。
        </c:if>
        <hr>
        <c:if test="${1 < 2}" >
            trueです。
        </c:if>
        <hr>
        <c:if test="${1 > 2}" >
            trueです。
        </c:if>
        <hr>
    </body>
</html>
  • 9~11行の出力結果を予想しなさい。
あなたの答え:
  • 13~15行の出力結果を予想しなさい。
あなたの答え:
  • 17~19行の出力結果を予想しなさい。
あなたの答え:


例題1

以下のif2.jspで20歳以上であれば「酒を飲む」と表示するJSTLをコメントの位置に書き入れなさい。

※繰り返しになりますが、JSTLのコメントは<%-- コメント --%>のように記述するのでした。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>if2</title>
    </head>
    <body>
        <%
            request.setAttribute("age", 20);
        %>
            <%--(ここに書く)--%>
    </body>
</html>

<c:if>タグではvar属性に変数名を指定すると、test属性に指定した条件式の判定結果のboolean値がその変数に格納されます。そのため以降の判定条件にその変数を使うことができます。

以下のif3.jspを読み込んで質問に答えてください。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>if2</title>
    </head>
    <body>
        <%
            request.setAttribute("count", 10);
            request.setAttribute("name", "imai");
        %>
        <c:if test="${count >= 10}" >
            count:<c:out value="${count}" />
        </c:if>
        <hr>
        <c:if test="${name == 'imai'}" var="flag" />
        imai?:<c:out value="${flag}" />
        <hr>
        <c:if test="${flag}" >
            imai
        </c:if>
        <hr>
        <c:if test="${!flag}" >
            imaiではない
        </c:if>
    </body>
</html>
  • 14~16行の出力結果を予想しなさい。
あなたの答え:
  • 18~20行の出力結果を予想しなさい。
あなたの答え:
  • 21~23行の出力結果を予想しなさい。
あなたの答え:
  • 25~27行の出力結果を予想しなさい。
あなたの答え:

<c:choose>

JavaSEのif文はelse句を使って処理を分岐させることができました。

しかし、JSTLの<c:if>タグにはelseはありません。

JSTLで多岐分岐を実現する場合は<c:choose>タグを使います

<c:choose>タグ の中には複数の<c:when>タグと、ひとつの<c:otherwies>タグを含めることができます。

<c:choose>の書式

<c:choose>

<c:when test = 判定条件1> 判定条件1が真の場合の処理 </c:when>

<c:when test = 判定条件2> 判定条件2が真の場合の処理 </c:when>

<c:otherwise> 判定条件1,2がともに偽の場合の処理 </c:otherwise>

</c:choose>

JavaSEのときに作成したBMI「体重kg/(身長m * 身長m )」を判定するプログラムを作成してみます。

JavaSEの場合は以下JavaSESampleIfElse.javaのようになりました。

package p07;

public class JavaSESampleIfElse {

    public static void main(String[] args) {

        double bmi = 70 / (1.7 * 1.7);

        if (bmi < 18.5) {
            System.out.println("低体重(やせ型)");
        } else if (bmi < 25) {
            System.out.println("普通体重");
        } else {
            System.out.println("肥満");
        }
    }
}

上記と同じことを以下choose1.jspではJSTLで実現しています。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>choose1.jsp</title>
    </head>
    <body>
        <%
            request.setAttribute("bmi", 70/(1.7*1.7));
        %>
        <c:choose>
            <c:when test="${bmi < 18.5}">低体重(やせ型)</c:when>
            <c:when test="${bmi < 25}">普通体重</c:when>
            <c:otherwise>肥満</c:otherwise>
        </c:choose>
    </body>
</html>

例題2

次のJavaSE(Q2.java )のプログラムと同様のことをJSTLを使って実現しなさい。

package p07;

public class Q2 {

    public static void main(String[] args) {

        int num = (int) (Math.random() * 101) % 9;

        if (num == 0) {
            System.out.println("大吉です");
        } else if (num == 1 || num == 2) {
            System.out.println("中吉です");
        } else if (num >= 3 && num <= 5) {
            System.out.println("小吉です");
        } else if (num == 6 || num == 7) {
            System.out.println("凶です");
        } else {
            System.out.println("大凶です");
        }
    }
}

また、switch文的な役割もこの<c:choose>タグが担います。

以下JavaSESampleSwitch.javaはJavaSEの血液型診断のプログラムです。(ちなみに筆者は血液型診断を信じません)

package p07;

public class JavaSESampleSwitch {

    public static void main(String[] args) {
        char bloodType = 'A';
        switch (bloodType) {
            case 'A':
                System.out.println("慎重な性格");
                break;
            case 'B':
                System.out.println("大胆な性格");
                break;
            case '0':
                System.out.println("おおらかな性格");
                break;
            default:
                System.out.println("不思議な性格");
        }
    }
}

上記と同じことをJSTLで実現するのが以下choose2.jspです。

ここでのポイントは、繰り返しになりますが、ELでは==で文字列が等しいかどうかの判定ができる点です。(JavaSEではequalsメソッドを使う必要がありました)さらに==をeqと書くこともできるのでしたね。(JavaSEではeqはありませんでした)

さらに、14、15行目をよく見てください。ELの場合は文字列をシングルクォーテーションでも囲むことができるのはダブルクォーテーションの中に入れられるようにするためでした。つまり、「"${bloodType == "A"}"」とすることはできませんが、「"${bloodType == 'A'}"」あるいは「'${bloodType == "A"}'」とすることはできるのです。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>choose2.jsp</title>
    </head>
    <body>
        <%
            request.setAttribute("bloodType", "A");
        %>
        <c:choose>
            <c:when test="${bloodType == 'A'}">慎重な性格</c:when>        <%--シングルクートで文字列を使った例--%>
            <c:when test='${bloodType == "B"}'>大胆な性格</c:when>        <%--ダブルクオートで文字列を囲んだ例--%>
            <c:when test='${bloodType eq "O"}'>おおらかな性格</c:when>    <%--eqを使った例--%>
            <c:otherwise>不思議な性格</c:otherwise>
        </c:choose>
    </body>
</html>

7.3 繰り返し

JSTLで繰り返しを実現するには<c:forEach>タグを使います

<c:forEach>の書式

<c:forEach>

繰り返したい処理

</c:forEach>

また、下表7.4の属性を指定できます。

属性意味
varvariableの略。繰り返し処理される値が代入される変数の名前(省略可)
itemsコレクションフレームワークを指定すれば、var属性で1つ1つの要素を取り出すことができるようになる
表7.4 <c:forEach>の属性

リストを使った繰り返し

<c:forEach> はJavaSEの拡張for文に似た使い方ができます

例えば、リストに入れた4人の名前を拡張for文を使って表示するには以下JavaSESampleFor.javaのように書きました。

package p07;

import java.util.ArrayList;
import java.util.List;

public class JavaSESampleFor {

    public static void main(String[] args) {
           
        for (int i = 0; i < 6; i++) {
            System.out.println("Hello World");
        }
        
        List<String> names = new ArrayList<String>();
        names.add("今");
        names.add("國分");
        names.add("田渕");
        names.add("久保川");
        
        for (String name : names) {
            System.out.println(name);
        }
    }
}

同様のことをしているのが以下foreach1.jspのサンプルコードです。

このときitems属性に指定できるのはリストなどのコレクションフレームワーク(や配列)のみであることに注意が必要です。

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>forEach1</title>
    </head>
    <body>

        <%
            List<String> names = new ArrayList<String>();
            names.add("今");
            names.add("國分");
            names.add("田渕");
            names.add("久保川");
            request.setAttribute("names", names);
        %>

        <c:forEach var="name" items="${names}">            
            ${name}<br>
        </c:forEach>

        <c:forEach var="name" items="${names}">            
            ${name}:${name.length()}文字<br>
        </c:forEach>    

    </body>
</html>
  • 28~30行の出力結果を予想しなさい。
あなたの答え:

例題3

上記のプログラムをできるだけ何も見ないで書きなさい。

オブジェクトを使った繰り返し

items属性に指定できるのはリストなどのコレクションフレームワークのみでした。

逆に言えばコレクションフレームワークであれば、その中身がどのようなオブジェクトでも指定できるということです。

以下のforeach2.jspを読み込んで質問に答えてください。

<%@page import="p06.CustomersBean"%>
<%@page import="p06.CustomerBean"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>forEach2</title>
    </head>
    <body>

        <%
            CustomerBean c1 = new CustomerBean();
            c1.setCustomerId(1);
            c1.setName("今井");
            c1.setPrefectureId(23);
            c1.setAddress("愛知県一宮市一丁目");
            c1.setBirthday("1992-01-16");
            c1.setPoints(100);
            CustomerBean c2 = new CustomerBean();
            c2.setCustomerId(2);
            c2.setName("田渕");
            c2.setPrefectureId(23);
            c2.setAddress("三重県桑名市一丁目");
            c2.setBirthday("1995-06-13");
            c2.setPoints(100);
            CustomersBean csb = new CustomersBean();
            csb.addCustomer(c1);
            csb.addCustomer(c2);
            request.setAttribute("customers", csb);
        %>

        <c:forEach var="customer" items="${customers.customerArrayList}">            
            ${customer}<br>
        </c:forEach>
        <hr>
        <c:forEach var="customer" items="${customers.customerArrayList}">            
            ${customer.name}<br>
        </c:forEach>
        <hr>
        <table border="1">
            <thead>
                <tr>
                    <th>顧客ID</th>
                    <th>顧客名</th>
                    <th>都道府県コード</th>
                    <th>顧客住所</th>
                    <th>顧客誕生日</th>
                    <th>ポイント</th>
                </tr>
            </thead>

            <tbody>
                <c:forEach var="customer" items="${customers.customerArrayList}">    
                    <tr>
                        <td>${customer.customerId}</td>
                        <td>${customer.name}</td>
                        <td>${customer.prefectureId}</td>
                        <td>${customer.address}</td>
                        <td>${customer.birthday}</td>
                        <td>${customer.points}</td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </body>
</html>
  • 38~40行の出力結果を予想しなさい。
あなたの答え:
  • 42~44行の出力結果を予想しなさい。
あなたの答え:
  • 46~70行の出力結果を予想しなさい。
あなたの答え:

今回はスクリプトレットで2名分の顧客オブジェクトを用意して、それぞれのデータを出力しました。

もう少し学習が進むとデータベースから取り出した全員の顧客の情報をオブジェクトに入れて一覧表にして出力することもできるようになります。それまであと一息ですので頑張りましょう。

例題4

以下の例を参考に顧客リストのテーブルにあなたのチームメンバーを加えなさい。

ただし、住所や誕生日はダミーでよい。

例題5

以前作成した以下のような数あてゲームのボタン版のフォームをforeachを使って作成しなさい。

なお、begin, end, varといったこのテキストに記述されていない属性を使う必要があるのでインターネットで各自調べること。

7.4 カートの中身を取り出す

前回のJavaBeansのところで作成したCarBeanクラスとCartクラスを使ってカートに商品を追加して、個々の商品と合計金額を表示するJSPを作成してみます。

これまでの知識を組み合わせれば以下cartSample1.jspのとおりです。

<%@page import="p06.Cart"%>
<%@page import="p06.CarBean"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>cartSample1.jsp</title>
    </head>
    <body>
        <%
        
        CarBean c1 = new CarBean("セダン", 2590000);
        CarBean c2 = new CarBean("クーペ", 4990000);
        Cart cart = new Cart();
        cart.addCar(c1);
        cart.addCar(c2);
        
        request.setAttribute("cart", cart);
        
        %>
        
        <c:forEach var="car" items="${cart.list}">            
            ${car.name}:${car.price}<br>
        </c:forEach>
            合計:${cart.total}        
    </body>
</html>

7.5 カートの中身を削除する

カートの中身を削除する処理は以下cartSample2.jspのように書きます。

<%@page import="p06.Cart"%>
<%@page import="p06.CarBean"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>cartSample2.jsp</title>
    </head>
    <body>
        <%
            CarBean c1 = new CarBean("セダン", 2590000);
            CarBean c2 = new CarBean("クーペ", 4990000);
            Cart cart = new Cart();
            cart.addCar(c1);
            cart.addCar(c2);
            cart.remove("セダン");
            request.setAttribute("cart", cart);
        %>
        <c:forEach var="car" items="${cart.list}">            
            ${car.name}:${car.price}<br>
        </c:forEach>
        合計:${cart.total}     
    </body>
</html>

単純な繰り返し

単純な繰り返しについては本研修では使用頻度が低いので以下の補講を見てください。

補講:JSTLをつかった単純な繰り返し

8. JSTLのi18nタグ

JSTLの i18nタグを使って金額や日付の表示フォーマットをコントロールできるようになりましょう。例えば金額に3桁のカンマを付けたり、日付を和暦で表示したりといったことができるようになります。当社が想定している最終課題をやり抜く上で特に重要なのが金額表示です。

8.1 金額の表示

例えば金額の先頭に¥マークを付けて3桁カンマ付きで金額を表示するには以下fmt1.jspのようにします。

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<fmt:formatNumber value="2590000" type="CURRENCY" currencySymbol="¥" maxFractionDigits="0" groupingUsed="true" />

結果を表示する

¥2,590,000

  • Coreタグを使用したときと何が同じで何が違いますか?
あなたの答え:

金額等の数値関連の属性としては下表7.5を押さえれば十分です。

属性説明
value数値データ
typeデータ型 CURRENCYは金額の意
currencySymbol="&yen;"をつけることで先頭に¥マークが付く、PERCENTは後ろに%が付く
groupingUsed3桁カンマの有無 trueは有り、falseは無し
maxFractionDigits小数部分の最大けた数(結果は四捨五入)
米ドルは小数点以下2桁まで表示するのが一般的だが日本円の場合は整数表示にするのが一般的なためmaxFractionDigits="0"とする
minFractionDigits小数部分の最小けた数 (結果は四捨五入)
表7.5 金額等の数値関連の属性

以下のfmt2.jspは金額等の数値関連の属性を使用したJSPです。

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<fmt:formatNumber value="2590000" type="CURRENCY"  groupingUsed="true" /><br>

<fmt:formatNumber value="3.141592" maxFractionDigits="3"/><br>

<fmt:formatNumber value="0.12345" type="PERCENT" minFractionDigits="1"/><br>

<fmt:formatNumber value="0.23456" type="PERCENT" minFractionDigits="1"/><br>

結果を表示する

¥2,590,000
3.142
12.3%
23.5%

8.2 日付の表示

次に日付の表示をコントロールしてみます。

以下fmt3.jspを見てください。

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<jsp:useBean id="date" class="java.util.Date"/>

<%
    java.util.Date theDay = new java.util.Date();
    request.setAttribute("theDay", theDay);
%>

<html>
    <body>
        <h4><fmt:formatDate value="${theDay}" pattern="yyyy年MM月dd日(E)" /> </h4>
        <h4><fmt:formatDate value="${theDay}" pattern="yy年M月d日(E)" /></h4>
        <h4><fmt:formatDate value="${theDay}" pattern="yyyy年" /></h4>
        <h4><fmt:formatDate value="${theDay}" pattern="MM月" /></h4>
        <h4><fmt:formatDate value="${theDay}" pattern="dd日(E)" /></h4>
    </body>
</html>

結果の例を表示する

2022年01月07日(金)
22年1月7日(金)
2022年
01月
07日(金)

日付関連の属性にpatternがあります。

本当はもっと多くのpatternがあるのですが、下表7.6を押さえれば当社の新人エンジニア研修では十分です。

なお、このpatternは多くのプログラミング言語やツール(例.EXCEL)でほぼ共通のものですから覚えて損はありません。

pattern意味(一般に文字数が桁数を意味する)
y西暦年(year)
M月(month)
d日(day)
E曜日
表7.6 日付関連のpattern属性

例題5

上記の例を参考に今日の日付をいろいろな表現で表示しなさい。

日付が文字列型である場合の注意点

この後データベース利用を学びますがMySQLで日付を文字列型で持たせるチームもあるかと思います。その場合はfmt4.jspの15行目のようにして、一旦Dateとしてparse(解析)する必要がありますので注意してください。

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<jsp:useBean id="date" class="java.util.Date"/>

<%
    java.util.Date theDay = new java.util.Date();
    request.setAttribute("theDay", theDay);
    
    request.setAttribute("dateString","2022-01-08");
%>

<html>
    <body>
        <fmt:parseDate var="date" value="${dateString}" pattern="yyyy-MM-dd" />
        <fmt:formatDate value="${date}" pattern="yyyy年M月d日" />
    </body>
</html>

最後に今回紹介したCoreタグとi18nタグについて下表7.7にまとめておきます。

種類Prefix URI
Corechttp://java.sun.com/jsp/jstl/core
Internationalization(i18n)fmthttp://java.sun.com/jsp/jstl/fmt
表7.7 Coreタグとi18nタグのまとめ

今回はELとJSTLについて学びました。

次回は、JDBCを学んでいきます。 JDBC を使えば、JSPやサーブレットとデータベースを組み合わせることができます。つまり、データベースから取り出したデータをBeansに入れて、<c:forEach>タグを使い拡張for文のような使い方をしてデータベースの内容を全てJSPに出力するということもできるようになります。

まとめ

□ ELの場合は文字列をシングルクォーテーションでもダブルクォーテーションでも囲むことができる

□ ELは==で文字列の比較ができる

□ ELを使うと JavaBeansのプロパティを簡単に出力できる

□ nullのオブジェクトをELに入れると何も出力されない

□ JSTLで単純分岐を実現するには<c:if>タグを使う

□ JSTLで多岐分岐を実現する場合は<c:choose>タグを使う

□ JSTLで繰り返しを実現するには<c:forEach>タグを使う

□ <c:forEach>タグはJavaSEの拡張for文に似た使い方もできるが、items属性に指定できるのはリストなどのコレクションフレームワークのみである点に注意する

□ JSTLの i18nタグを使うと金額や日付の表示フォーマットをコントロールできる

JavaWebアプリケーション目次に戻る