JSTL coreタグライブラリの利用

# JSTL (Java Server Pages Tag Library) 

JSTLは、一般によく利用されるカスタムタグをまとめ、Apache Taglibs Project (旧Jakarta Taglibs Project)が配布しているもの。

以下で紹介するタグのドキュメントは、[Oracleのドキュメント](http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/)を参照。

# JSTLを利用する

### ライブラリの配置

1. [JSTLのサイト](https://tomcat.apache.org/taglibs/standard/)から必要なバージョンのstandard.jar, jstl.jarを取得する。古いバージョンはzipでまとめて配布されている。
2. プロジェクトのWEB-INF/lib以下にそれらを配置する。

### JSP内での利用宣言

JSP内で以下を記述し、プレフィックス`c`をつけてタグライブラリを利用する旨を宣言する。

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

### コード中での記述

taglibディレクティブで宣言した接頭辞とタグの名前をコロンでつないで記述する。

```jsp:ifの例
<c:if test="真偽式">
  真偽式が真の時に表示するコード
</c:if>
```


# coreライブラリ紹介(制御系)

## \<c:if\>: 条件分岐

実行するかしないかの条件分岐をする。

```jsp:例
<%
  int userCnt = 5;
%>
<c:if test="${userCnt >= 3}">
  3人以上のユーザがいます。
</c:if>
```
```html:出力HTML
  3人以上のユーザがいます。
```

ifは以下の属性を持つ。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| test     | ○     | 値が真のとき、body部を出力する |
| var      |       | testの評価結果を格納する変数名を指定する |
| scope    |       | varのスコープを指定する |
| (body部) |       | test結果が真のときに表示する内容を記述する |

## \<c:choose\>, \<c:when\>, \<c:otherwise\>: 多分岐

chooseで全体を囲み、when, otherwiseを内部に書く。
chooseの中で最初にtestが真になったwhen節を採用する(採用したもの以下のwhen節は全て無視する)。
全て偽の場合、otherwise節があれば採用する。

EL式を利用すると記述しやすい。

```jsp:例
<%
  int userCnt = 60;
%>
<c:choose>
  <c:when test="${userCnt > 100}">100人以上が利用しています。</c:when>
  <c:when test="${userCnt > 50}">50人以上が利用しています。</c:when>
  <c:when test="${userCnt > 5}">5人以上が利用しています。</c:when>
  <c:othewise>あまり人がいません。</c:othewise>
</c:choose>
```
```html:出力HTML
  50人以上が利用しています。
```

whenにだけ属性がある。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| test     | ○     | 値が真のとき、このwhen節を採用する |

最初にtestが真になったwhen節を採用する。
全て偽の場合、otherwise節があれば採用する。

## \<c:forEach\>: コレクションの走査

配列やコレクションを走査する。Javaのfor-eachとおよそ同等のことができる。

```jsp:例
<%
  String[] strs = {
    "最初の行",
    "真ん中の行",
    "最後の行",
  };
  request.setAttribute("list", strs);
%>
<table>
  <c:forEach var="v" items="${list}" varStatus="st">
    <tr><td>${st.count}番目</td><td>${v}</td></tr>
  </c:forEach>
</table>
```
```html:出力HTML
<table>
    <tr><td>1番目</td><td>最初の行</td></tr>
    <tr><td>2番目</td><td>真ん中の行</td></tr>
    <tr><td>3番目</td><td>最後の行</td></tr>
</table>
```

forEachには多くの属性がある。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      |       | itemsから取り出した1要素を格納する変数の名前 |
| items    |       | 走査するリストを指定する(EL式などを使う) |
| begin    |       | 走査の開始要素番号 |
| end      |       | 走査の終了要素番号 |
| step     |       | 走査の1ステップあたりの進行数 |
| varStatus |      | 繰り返しの状態を格納する変数の名前 |
| (body部) |       | 各繰り返しに対して表示する内容を記述する |

varStatusに指定した変数からは以下の情報が取得できる。

| プロパティ | 概要 |
| :--- | :------- |
| current | 現在走査している要素 |
| index | 現在走査している要素の番号 |
| count | ループの何回目の実行か |
| first | 今がループの初回かどうか(真偽値) |
| last | 今がループの最後かどうか(真偽値) |
| begin | beginに設定した数値 |
| end | endに設定した数値 |
| step | stepに設定した数値 |

## \<c:forTokens\>: 文字列を分割して走査

文字列を指定したデリミタで区切り、その要素を走査する。
Javaで考えると、 `for (String s: data.split(","))` という感じ。

```jsp:例
<%
  String str = "foo,bar,hoge,fuga"
  request.setAttribute("data", str);
%>
<table>
  <c:forTokens var="s" items="${data} delims="," varStatus="st">
    <tr><td>${st.index}番目</td><td>${s}</td></tr>
  </c:forTokens>
</table>
```
```html:出力HTML
<table>
    <tr><td>0番目</td><td>foo</td></tr>
    <tr><td>1番目</td><td>bar</td></tr>
    <tr><td>2番目</td><td>hoge</td></tr>
    <tr><td>3番目</td><td>fuga</td></tr>
</table>
```

forTokensには以下の属性を指定できる。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      |       | itemsから取り出した1要素を格納する変数の名前 |
| items    | ○     | 分割する文字列を指定する |
| delims   | ○     | 文字列の区切り子を指定する |
| begin    |       | 走査の開始要素番号 |
| end      |       | 走査の終了要素番号 |
| step     |       | 走査の1ステップあたりの進行数 |
| varStatus |      | 繰り返しの状態を格納する変数の名前(forEachと同様) |
| (body部) |       | 各繰り返しに対して表示する内容を記述する |

## \<c:catch\>: 例外の捕捉

body部で発生したThrowableを捕捉する。
捕捉しかしない。いわゆるcatchブロックに相当するものは別に記述が必要。
`try` ブロックのイメージ。

```jsp:例
<c:catch var="exception">
  <%
    int inf = 3 / 0;
  %>
</c:catch>

<c:if test="${exception != null}">
  <c:out value="${exception.message}" />
</c:if>
```

```HTML:出力HTML
  / by zero
```

catchの属性はひとつ。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      |       | 例外を格納する変数の名前 |
| (body部) |       | (例外が発生しうる)処理 |



# coreライブラリ紹介(変数系)

## \<c:out\>: 出力

出力に用いる。
単純にEL式を記述すれば出力自体はできるが、outタグを用いると、以下の処理ができる。

- 出力対象がnullのときの出力を決定できる。
- XMLエスケープして出力できる。

```jsp:例
<%
  request.setAttribute("sampleVar", new Integer(300));
%>

<c:out value="${sampleVar}"/>

<c:out value="${'<div> name & string </div>'}" />
<c:out value="${'<div> name & string </div>'}" escapeXml="false" />

<c:out value="${null}" default="<div> nullでした(1)。 </div>" />
<c:out value="${null}"> <div> nullでした。 </div> </c:out>
```

```HTML:出力HTML
300

&lt;div&gt; name &amp; string &lt;/div&gt;
<div> name & string </div>

&lt;div&gt; nullでした(1)。 &lt;/div&gt;
&lt;div&gt; nullでした。 &lt;/div&gt;
```

outの属性はこれら。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      | ○     | 出力内容 |
| default  |       | varがnullの場合に出力する内容。body部と排他 |
| escapeXml |      | XMLエスケープを行うかどうかの真偽値。デフォルトでは真(行う) |
| (body部) |       | varがnullの場合に出力する内容。defaultと排他 |

defaultとbody部を同時に指定すると不正なタグで500エラーになる。


## \<c:set\>: 値のセット

スコープに値を登録したり、Beanのプロパティをセットしたりできる。

```jsp:例
<c:set var="myset" value="${3 + 12 / 5}" />
<c:set var="myBodySet"><div> body set </div></c:set>

<c:out value="${myset}" />
<c:out value="${myBodySet}" />
```

```HTML:出力HTML
5.4
&lt;div&gt; body set &lt;/div&gt;
```

以下の属性が利用できる。ただし、 (var,scope) と (target,property) は排他。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      |       | 値をセットする変数 |
| scope 　 |       | varのスコープ。(page,request,session,application)のどれか。デフォルトはpage |
| target   |       | 値をセットするpropertyを持つオブジェクト名 |
| property |       | セットしたいプロパティ名 |
| value    |       | varにセットする値。body部と排他 |
| (body部) |       | varにセットする値。valueと排他 |

propertyに指定した名前は、targetに指定したオブジェクトのクラスに単純セッター(`setXxx()`関数)が必要。


## \<c:remove\>: 削除

スコープにある変数を削除できる。

```jsp:例
<c:set var="myset" value="${3 + 12 / 5}" />
<c:out value="${myset}" />

<c:remove var="myset" />
<c:out value="${myset}" default="mysetはnullです。" />
```

```HTML:出力HTML
5.4

mysetはnullです。
```

removeで利用する属性は以下。scopeを間違えると削除できないので注意する。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| var      | ○     | 値を削除する変数 |
| scope    |       | varのスコープ。(page,request,session,application)のどれか。デフォルトはpage |



# coreライブラリ紹介(Web系)

## \<c:param\>: リクエストパラメータの指定

(import,redirect,url)タグのbodyで、リクエストパラメータを指定する。

```jsp:例
<!%-- 次の2行は同等 --%>
<c:param name="test" value="100" />
<c:param name="test">100</c:parm>
```

属性は非常に単純。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| name     | ○     | パラメータ名 |
| value    |       | パラメータの値。body部と排他 |
| (body部) |       | パラメータの値。valueと排他 |


## \<c:import\>: ファイルの動的インポート

コンテンツを取り込む。includeディレクティブよりも高機能だが、動的取り込みなので遅い(らしい)。

```jsp:例
<!%-- 取り込み内容をそのまま表示する --%>
<c:import url="/util/header.jsp" />
<!%-- 取り込み内容を変数に格納 --%>
<c:import url="/data/item.txt" var="text"/>
<!%-- 取り込んだバイナリを変数に格納 --%>
<c:import url="/img/main.png" varReader="imgReader"/>
<!%-- body部を利用したパラメータ指定 --%>
<c:import url="/util/header.jsp">
  <c:param name="username" value="hoge" />
</c:import>
```

importの属性は多い。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| url      | ○     | 取り込むURL |
| context  |       | urlが/から始まる場合に探索するコンテキストパス |
| charEncoding |   | 取り込むものの文字エンコード |
| var      |       | 取り込んだものを格納する変数 |
| scope    |       | varをセットするスコープ |
| varReader |      | 取り込んだバイナリを格納する変数 |
| (body部) |       | paramタグを使ってリクエストパラメータを指定できる |

varもしくはvarReaderを指定しない場合、取り込んだ内容をそのまま出力する。
urlに指定できるものは、`java.net.URL`による。
varReaderは、`java.io.Reader`のインスタンスになる。

## \<c:redirect\>: リダイレクト

`javax.servlet.http.HttpServletResponse`クラスの`sendRedirect(String)`関数と同様の機能を持つ。

```jsp:例
<c:redirect url="/foo/other.jsp" />
<!%-- パラメータを指定する場合、body部で指定する -->
<c:redirect url="/foo/other.jsp">
  <c:param name="test" value="100" />
</c:redirect>
```

リダイレクトを行うだけなので、属性は少ない。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| url      | ○     | リダイレクト先URL |
| context  |       | urlが/から始まる場合に探索するコンテキストパス |
| (body部) |       | paramタグを使ってリクエストパラメータを指定できる |

リダイレクト元で既にレスポンスがコミットされている場合、`IllegalStateException`となる。

## \<c:url\>: URLエンコード

URLエンコードを行う。
importやredirectするURLに利用できる。

```jsp:例
<c:url value="http://www.google.com/search" var="searchURL" >
  <c:param name="q" value="sample" />
</c:url>
<a href="<c:out value="${searchURL}" />">search</a>
```

urlタグの属性は以下。

| 属性     | 必須   | 概要 |
| :------  | :---: | :--- |
| value    | ○     | 生成する基準となるURL |
| context  |       | valueが/から始まる場合に探索するコンテキストパス |
| var      |       | URLを格納する変数 |
| scope    |       | varをセットするスコープ |
| (body部) |       | paramタグを使ってリクエストパラメータを指定できる |


----------------------------------

# 参考

JSTLドキュメント http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/

JSTL Project https://tomcat.apache.org/taglibs/standard/