OKLabのタイトルロゴ

JSTL入門

目次

はじめに

JSTLの全体像を数時間で説明する入門です。JSTLとは何かを説明した後に、簡単なJSPとJSTLのソースコードを比較しながら学習します。

JSTLとは

JSTL(Java Server Pages Standard Tag Library)とは、JSPのバージョン2.0で標準化されたタグの集まりです。サンマイクロシステムズが開発したので実質的な標準です。

すこし昔をおさらいしたいと思います。2000年ごろサーブレットが開発で利用されるようになりました。このころはサーブレットのAPIをつかいJavaのソースコードの中にHTMLを記述していました。当然ちょっと修正するのにもコンパイルが必要だったため、その要望の答えて、JSPが開発されました。JSPはご存知の通り、HTML内にソースコードを書くことが出来るので、修正に強くなりました。

しかし、便利でいろいろな開発に使われると、JSPでの組み込まれたソースコードが、可読性やデザイナとの関連で問題になりました。そのため、Javaのソースコードをなるべく書かないようにしようと各自タグの集まり(ライブラリ)を作るようになりました。その集大成のひとつとしてStrutsフレームワークがあげられます。

StrutsフレームワークにもJSTLをまったく同じ機能のタグがあります。このような便利なものは様々なところで乱立して作られていたので標準化団体がJSTLをして仕様を決め生み出されました。

このような背景から、JSTLは、JSPファイル内にソースコードを書かないようにするタグの集まりとなっています。

対象読者

読みたい人。JSTLの細かい部分まで深く学ぶのではなく、ちょっとしたサンプルを見ながら全体像を理解したい人にお勧めです。

動作確認

ここのサンプルをテストした動作環境です。

インストール

前提条件として、JDK,Tomatがインストールしていなければなりません。これらのインストールについては、WEB上に情報が多くありますのでここでは説明しません。http://japache.infoscience.co.jp/apache/dist/jakarta/taglibs/standard/からjakarta-taglibs-standard-1.0.3.tar.gzをダウンロードします。ダウンロードしたら中に何が入っているか確認してみましょう


# tar -zxvf jakarta-taglibs-standard-1.0.3.tar.gz
# cd jakarta-taglibs/standard-1.0.3/
ディレクトリ名 備考
README このディレクトリの説明
javadoc
lib jstl.jarなどがあります。開発の際はWEB-INF/libに置くようにします。(詳細はあとで説明)
standard-doc.war JSTLの概要が書いてあります
standard-examples.war サンプル集。
tld タグライブラリディスクリプタ

サンプルの登録(推奨)

私もそうですが、英語が読めなくてもjavaのソースであればなんとなく読めるという方は standard-doc.war,standard-examples.warをtomcatのwebappに置くことをお勧めします。 tomcatの初期設定の場合、warファイルを展開してくれます。


# cp *.war $CATALINA_HOME/webapp/.

展開されているのが確認できたら以下でアクセスしてみましょう。サンプルや概要が確認できます

http://127.0.0.1:8080/standard-doc

http://127.0.0.1:8080/standard-examples

testコンテキストの作成と確認

これからサンプルを動作させるためのコンテキストを作成します。またそこにweb.xmlとindex.htmlを作成して 動作確認もします。


# cd $CATALINA_HOME/webapp
# mkdir -p test/WEB-INF

ここにweb.xmlを作成します。


<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
        <display-name>bbs</display-name>
        <description></description>
        <welcome-file-list>
                <welcome-file>index.jsp</welcome-file>
                <welcome-file>index.html</welcome-file>
        </welcome-file-list>
</web-app>

<welcome-file-list>を記述したのでindex.htmlを適当に作成します。


<html lang="ja">
<head>
<title></title>
</head>
<body topmargin="0" bottommargin="0" rightmargin="0" leftmargin="0" marginwidth=
"0" marginheight="0" bgcolor="#eeeeee">
index.html
</body>
</html>

それでは、testコンテキストにアクセスしてテストしてみましょう。

http://127.0.0.1:8080/test/index.html

ライブラリの配置

先ほど作成した$CATALINA_HOME/webapp/test/WEB-INFにlibディレクトリを作成します。 そこにJSTLのライブラリstandard.jarを配置します。


# jakarta-taglibs/standard-1.0.3/
# cd /opt/tomcat/webapps/test/WEB-INF
# mkdir lib
# cd lib
# cp XXX/jakarta-taglibs/standard-1.0.3/lib/
# cp /usr/local/src/jakarta-taglibs/standard-1.0.3/lib/standard.jar .
# cp /usr/local/src/jakarta-taglibs/standard-1.0.3/lib/jstl.jar .

お疲れ様です。これでようやくJSTL実行環境が整いました。

とりあえずHelloWorld!

<%@ page content="text/html; charset=Shift_JIS" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:out value="HelloWorld!" />

2行目でJSTLのcoreを使えるように宣言。

3行目でHelloWorld!と出力している<%= "HelloWorld!" %>と同じ意味

JSTLは、JSPからスクリプトレットを排除することが目的のようです。

JSTLで使えるタグライブラリ一覧

Javaでライブラリを利用するときはimport文を使います。JSTLでライブラリを使うということは、 サンマイクロシステムズ社が作ったタグの集まりを使うことになります。利用したい場合は、 taglib宣言をしなければいけません。

taglib宣言とimport文との違いは、パッケージ名を書くのではなく、uri属性にuri(url)を書くことです。 そしてプレフィックスを指定します。以下にサンプルを2つ書きました。プレフィックスが違うことに 注意してください。

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

プレフィックスがcなので、コアのJSTLライブラリを<c: xxx>という書き方で使えます。

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

この例の場合は、プレフィックスがsun_coreなので、コアのJSTLライブラリを<sun_core: xxx>という書き方で使えます。

プレフィックスというのは、このライブラリはこの接頭語を使って書きますよ。と宣言しているだけ ですので、ユーザが好きに指定できます。

プレフィックス 備考 宣言の仕方
c JSTLの一般的なタグ、入出力、分岐など <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
x XMLデータを処理するタグ <%@ taglib uri="http://java.sun.com/jstl/xml" prefix="xml" %>
fmt 国際化のタグ <%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
sql SQLを処理するタグ <%@ taglib uri="http://java.sun.com/jstl/sql" prefix="sql" %>

coreタグ一覧

coreタグは、もっとも単純なタグの集まりで、htmlには存在しない分岐や繰り返し処理を可能にします。またJSPを 使う場合は、サーバとのデータのやり取りをJavaのオブジェクトを通しておこなうので、そのオブジェクトの任意のデータを 表示したり、オブジェクトを開放したりするタグなどがあります。以下がライブラリの一覧になります。

JSTL JSP 備考
<c:out> <%= %>または<% out.println("hoge"); %> コードをHTMLに出力するために利用
<c:set> <jsp:useBean /> データをオブジェクトに格納する
<c:remove> オブジェクトの削除
<c:catch> 例外の取得
<c:if> if分岐
<c:choose> whenタグ、chooseタグを利用する時に囲む
<c:when> select文などのように複数分岐する時に利用
<c:otherwise>

チュートリアル

  JSTLとJSPのサンプルで、違いを確認していきたいと思います。JSTLでコーディングすると、タグだけになるので、JSPのスクリプトレット記述よりも読みやすいのがわかると思います。

入出力や分岐処理

<c:out>と<c:set>

<c:set>は、変数を定義するものです。この例だとscope="page"と指定しているのでこのページのみで参照できる変数hogehogeを値fugafugaとして定義しています。その後、<c:out>で表示しています。

JSTLのサンプル JSPのサンプル

<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set value="fugafuga" var="hogehoge" scope="page"/>
<c:out value="${hogehoge}"/>

<%@ page contentType="text/html; charset=shift_jis" %>

<%	pageContext.setAttribute("hogehoge","fugafuga"); %>
<%=	pateContext.getAttribute("hogehoge") %>

<c:remove>

オブジェクトの開放には、<c:remove>を使います。以下の例は、<c:set>でpageスコープにString hogehoe = "fugafuga"と定義して、そのご <c:remove>を呼ぶことでhogehoge = nullのような開放を行っています。その後、 <c:out>で値を表示しても"fugafuga"とは表示されません。


<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var="hogehoge" value="fugafuga" scope="page"/>
<c:remove var="hogehoge" scope="page"/>
<c:out value="${hogehoge}"/>

<%@ page contentType="text/html; charset=shift_jis" %>
<%   pageContext.setAttribute("hogehoge", "fugafuga");
        pageContext.setAttribute("hogehoge", "");
        out.println(pageContext.getAttribute("hogehoge")); %>

<c:catch>と<c:if>

分岐処理には、<c:if>を使います。また例外の補足には、<c:catch>を使います。例外を発生させるタグは存在しないためデバッグなどで意図的に例外を発生させたい場合は、JSPのように<%でスクリプトレットを記述する必要があります。


<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:catch var="test1">
<c:out value="before exception" /><br>
<c:if test="${1/0}">TEST OK</c:if>
<c:out value="after exception" /><br>
</c:catch>
<c:out value="${test1.message}"/>

<%@ page contentType="text/html; charset=shift_jis" %>

<%      try {
                out.println("before exception");
                if (true) throw new Exception("test exception");
                out.println("after exception");
        } catch (Exception ex) {
                        out.println(ex); } %>

<c:choose><c:when><c:otherwise>

通常プログラミング言語にはcase文が備えられています。JSTLではchoose,when,otherwiseを使うことで同じ事ができます。


<%@ page contentType="text/html; charset=shift_jis" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var="count" value="3" scope="request"/>
<c:choose>
	<c:when test="${count == 1}">ONE</c:when>
	<c:when test="${count == 2}">TWO</c:when>
	<c:when test="${count == 3}">THREE</c:when>
	<c:otherwise>other!!!</c:otherwise>
</c:choose>

<%@ page contentType="text/html; charset=shift_jis" %>

<% request.setAttribute("count", "3");
String tmpCount = request.getAttribute("count");
if ( tmpCount.equals("1")) out.println("ONE");
else if ( tmpCount.equals("2")) out.println("TWO");
else if ( tmpCount.equals("3")) out.println("THREE");
else out.println("ohter!!!");
%>

Iteratorタグ一覧

JSTL JSP 備考
<c:forEach>   オブジェクトのイテレート。ArrayListのデータ取出しなどで利用。
<c:forTokens>   デミリタで区切る。Stringをカンマで区切るときなどに利用。

繰り返し処理の例

<c:forEach>を使った繰り返し処理の例です。JSPが生まれたときは、JSPファイル内に直接ソースコードを埋め込む事で 繰り返し処理をしていました。JSTLの場合はタグが用意されています。

サンプルでは、分かりやすいように、テストデータを<% xx %>と書かれているスクリプトレットで書いていますが、 実際のソースコードでは、この部分がなくなるので、HTMLとJSTLのタグのみで読みやすいソースコードになります。

JSTLのサンプル JSPのサンプル

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ page import="java.util.ArrayList" %>
<%
ArrayList al = new ArrayList();
al.add("ONE");
al.add("TWO");
al.add("THREE");
session.setAttribute("al",al.iterator());
%>
<c:forEach var="element" items="${al}">
<c:out value="${element}"/>
</c:forEach>

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ page import="java.util.ArrayList, java.util.Iterator" %>
<%
ArrayList al = new ArrayList();
al.add("ONE");
al.add("TWO");
al.add("THREE");
Iterator it = al.iterator();

while (it.hasNext()) {
	out.println((String)it.next());
} %>

国際化タグ一覧

国際化したサイトを作る場合には、HTMLやJSPに直接日本語や英語を書かず、外部ファイルに記述しておいたほうがよい場合があります。こういう場合は、リソースバンドルという機能を使います。JSPの場合は、JavaのAPIから直接ResourceBundleクラスを呼び出さなければなりません。けれどJSTLの場合はリソースバンドル用のタグが用意されています。

JSTL JSP 備考
<fmt:setLocale>
<fmt:bundle>
<fmt:setBundle> 利用するリソースを指定します。通常はプロパティファイルになるとおもいます。
<fmt:message> メッセージキーを指定します。
<fmt:param>
<fmt:requestEncoding>

リソースバンドルの例

JSTLのサンプル JSPのサンプル

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
<fmt:setLocale value="en_US" />
<fmt:setBundle basename="test" />
<html>
<body>
<fmt:message key="hoge" />
<fmt:message key="aahoge" />
</body>
</html>

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ page import="java.util.ResourceBundle" %>


<html>
<body>
<%= ResourceBundle.getBundle("test").getString("hoge") %>
<%= ResourceBundle.getBundle("test").getString("aahoge") %>
</body>
</html>

言語をダイナミックに切り替えてみる。

JSTLのサンプル JSPのサンプル

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt"  prefix="fmt" %>
<html>
<body>
<c:choose>
<c:when test="${param.lang == 'en'}">
<fmt:setBundle basename="Message_en" />
<fmt:setLocale value="en" />
</c:when>
<c:when test="${param.lang == 'ja'}">
<fmt:setBundle basename="Message_ja" />
<fmt:setLocale value="ja" />
</c:when>
</c:choose>
<form action="aaa.jsp" target="_self">
<select name="lang">
<option value="en">english</option>
<option value="ja">japanese</option>
</select>
<input type="submit" name="submit" value="submit">
<fmt:message key="hello_world" />
</form>
</body>
</html>

暗黙オブジェクト(implicit object)

RequestスコープのオブジェクトやSessionスコープのオブジェクトを使うと、Requestのヘッダ情報やクッキーの情報など を入手することが可能です。JSPでは宣言しなくても暗黙オブジェクトとして直ぐ使うことが出来ました。JSTLでも同様に 使うことが出来ます。またJSTLの暗黙オブジェクトの方が簡単に使えるように設計されています。

以下に暗黙オブジェクトの一覧を記述します。

JSTL JSP
pageScope pageContext
requestScope request
sessionScope session
applicationScope application
param.xxx request.getParameter("xxx")
paramValues request.getParameterValues()#Enumeration
header getHeader?
headerValues ?
initParam ?
cookie ?
PageContext can get all properties

Sessionオブジェクト

sessonオブジェクトを使ったセッションのサンプル

JSTLのサンプル JSPのサンプル

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var="hoge" value="ok" scope="session" />
<c:redirect url="/sessionTestResult.jsp" />

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<head>
<title>sessionTestResult.jsp</title>
</head>
<body>
<c:out value="${sessionScope.hoge}" />
</body>
</html>

<%@ page contentType="text/html; charset=iso-8859-1" %>
<% session.setAttribute("hoge", "ok"); %>
<jsp:forward page="/sessionTestJSPResult.jsp" />


<%@ page contentType="text/html; charset=iso-8859-1" %>

<html>
<head>
<title>sessionTestResult.jsp</title>
</head>
<body>
<%= session.getAttribute("hoge") %>
</body>
</html>

自分で作成したBeanをセッションとして使うサンプル

JSTLのサンプル JSPのサンプル

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<jsp:useBean class="test.MySession" 
id="mySession" scope="session"/>
<c:out value="hoge"/>
<c:set target="${mySession}" property="name" value="GOGOGO" />
<c:redirect url="/mySessionJSTLResult.jsp" />

<%@ page contentType="text/html; charset=iso-8859-1" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<jsp:useBean class="test.MySession" 
id="mySession" scope="session" />
<html>
<head>
<title>mySessionResult.jsp</title>
</head>
<body>
<c:out value="${mySession.name}"/>
</body>
</html>

<%@ page contentType="text/html; charset=iso-8859-1" %>

<jsp:useBean class="test.MySession"
id="mySession" scope="session"/>

<jsp:setProperty name="mySession" property="name" value="GOGOGO" />
<jsp:forward page="/mySessionResult.jsp" />

<%@ page contentType="text/html; charset=iso-8859-1" %>

<jsp:useBean class="test.MySession" 
id="mySession" scope="session" />
<html>
<head>
<title>mySessionResult.jsp</title>
</head>
<body>
<jsp:getProperty name="mySession" property="name" />
</body>
</html>
セッション用のBean

package test;

public class MySession {
	private String name;

	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
}

$Id$