ASH | サーバ | セキュリティ | Linux | FreeBSD | DB | Web | CGI | Perl | Java | XML | プログラム | ネットワーク | 標準 | Tips集

繰り返しカスタムタグ

forEachカスタムタグ

forEachカスタムタグの仕様

 forEachカスタムタグでは、繰り返しオブジェクトのデータを、順番に文字型(java.lang.String)の変数の値に、順番に設定します。 itemsは、Array型、Collection型(Vector型)、Iterator型の繰り返しオブジェクトが利用できます。 Enumeration型には対応していませんので、Iterator型を使ってください。
 type属性で、設定する変数のクラスを指定することもできます。 複数の項目を繰り返す場合は、クラスを作成し、そのクラス名を指定します。

<ash:forEach var="変数名" type="変数クラス名" items="繰り返し型変数">
  <%=変数名%>を使ったJSPの記述
</ash:forEach>

タグハンドラのソース(ForEachTag.java)

 タグハンドラは、doStartTag、doAfterBodyメソッドを実装します。 タグハンドラの処理では、各種繰り返し型のオブジェクトを、Iterator型に変換しています。 Iterator型の場合は、hasNext()メソッドと、next()メソッドが必要となります。

ForEachTag.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.util.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

/**
 * forEach繰り返し表示タグライブラリ
**/
public class ForEachTag extends TagSupport {
  private String var;
  private String type;
  private Object items;
  private Iterator iterator;

  /** varの設定 **/
  public void setVar(String var) {
    this.var = var;
  }
  /** typeの設定 **/
  public void setType(String type) {
    this.type = type;
  }
  /** itemsの設定 **/
  public void setItems(Object items) {
    this.items = items;
  }

  /** タグ初期処理(繰り返しの初期処理) **/
  public int doStartTag() throws JspException {
    // データがない場合は処理しない
    if (items == null) {
      return SKIP_BODY;
    }

    // Array型からIteratorに変換
    if (items instanceof Object[]) {
      Object[] array = (Object[]) items;
      iterator = Arrays.asList(array).iterator();

    // Collection型からIteratorに変換
    } else if (items instanceof Collection) {
      Collection collection = (Collection) items;
      iterator = collection.iterator();

    // Iterator型からIteratorに変換
    } else if (items instanceof Iterator) {
      iterator = (Iterator) items;

    // その他のデータ型の場合はエラー
    } else {
      throw new JspException("Invalid type: " + items.getClass().getName());
    }

    // 次の要素を取得
    if (iterator.hasNext()) {
      pageContext.setAttribute(var, iterator.next());
      return EVAL_BODY_INCLUDE;

    } else {
      return SKIP_BODY;
    }
  }

  /** 繰り返しの後処理 **/
  public int doAfterBody() throws JspException {
    // データがない場合は処理しない
    if (iterator == null) {
      return SKIP_BODY;
    }

    // 次の要素を取得
    if (iterator.hasNext()) {
      pageContext.setAttribute(var, iterator.next());
      return EVAL_BODY_AGAIN;

    } else {
      return SKIP_BODY;
    }
  }
}

タグ拡張情報のソース(ForEachTEI.java)

 タグ拡張情報では、設定する変数名(var)を定義します。

ForEachTEI.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import javax.servlet.jsp.tagext.*;

/**
 * forEachタグライブラリの変数定義
**/
public class ForEachTEI extends TagExtraInfo {
  public VariableInfo[] getVariableInfo(TagData tagData) {
    String varName = tagData.getAttributeString("var");
    String varType = tagData.getAttributeString("type");
    if (varType == null) { varType = "java.lang.String"; }

    return new VariableInfo[] {
      new VariableInfo(varName, varType, true, VariableInfo.NESTED)
    };
  }
}

forEachカスタムタグを使った住所録の表示

 forEachカスタムタグを使って、Array型のデータと、Vector型のデータの住所録データを表示してみます。

画面イメージ

住所録×
住所録
Array型
名前住所電話
升村 丞金沢市菊川076-261-4921
北陸 太郎金沢市大手町076-221-1429
金沢 花子金沢市片町090-2377-2056
Vector型
名前住所電話
升村 丞金沢市菊川076-261-4921
北陸 太郎金沢市大手町076-221-1429
金沢 花子金沢市片町090-2377-2056

JSPのソース

 forEachカスタムタグは、Array型にもVector型にも対応しているため、同じようにitemsに繰り返し変数を指定するだけで、addrオブジェクトが順番に設定され、繰り返されます。

Addr.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib prefix="ash" uri="http://ash.jp/taglib_1_0" %>

<%@ page import="java.util.*" %>
<%!
  class AddrData {
    String name;
    String address;
    String tel;

    AddrData (String name, String address, String tel) {
      this.name = name;
      this.address = address;
      this.tel = tel;
    }
  }
%>
<%
  // Array型住所録データ作成
  AddrData[] addrArray = new AddrData[] {
    new AddrData("升村 丞",   "金沢市菊川",   "076-261-4921"),
    new AddrData("北陸 太郎", "金沢市大手町", "076-221-1429"),
    new AddrData("金沢 花子", "金沢市片町",   "090-2377-2056")
  };

  // Vector型住所録データ作成
  Vector addrVector = new Vector();
  addrVector.add(new AddrData("升村 丞",   "金沢市菊川",   "076-261-4921"));
  addrVector.add(new AddrData("北陸 太郎", "金沢市大手町", "076-221-1429"));
  addrVector.add(new AddrData("金沢 花子", "金沢市片町",   "090-2377-2056"));
%>

<html>
<head><title>住所録</title></head>
<body>

<h1>住所録</h1>

<h2>Array型</h2>

<table border="2">
<ash:forEach var="addr" type="AddrData" items="<%= addrArray %>">
  <tr>
    <td><%= addr.name %></td>
    <td><%= addr.address %></td>
    <td><%= addr.tel %></td>
  </tr>
</ash:forEach>
</table>

<h2>Vector型</h2>

<table border="2">
<ash:forEach var="addr" type="AddrData" items="<%= addrVector %>">
  <tr>
    <td><%= addr.name %></td>
    <td><%= addr.address %></td>
    <td><%= addr.tel %></td>
  </tr>
</ash:forEach>
</table>

</body>
</html>

forEachカスタムタグのテスト

forEachカスタムタグテスト用画面イメージ

 JSPで、Array型やCollection型(Vector型)やIterator型の、繰り返しデータの内容を表示します。 以下に、この画面を表示するためのサンプルソースを示しています。

forEachタグのテスト×
forEachタグのテスト
Array
data01data02data03
Collection(Vector)
data01data02data03
Iterator
data01data02data03

forEachカスタムタグテスト用JSPのソース(ForEach.jsp)

 ForEach.jspは、ForEachサーブレットから呼び出されます。
 JSPのソースでは、Array型、Collection(Vector)型、Iterator型の繰り返し変数の内容を表示しています。

ForEach.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib prefix="ash" uri="http://ash.jp/taglib_1_0" %>
<jsp:useBean id="foreach" class="jp.ash.taglib.ForEachData" scope="request" />

<html>
<head><title>forEachタグのテスト</title></head>
<body>

<h1>forEachタグのテスト</h1>

<h2>Array</h2>

<table border="2"><tr>
<ash:forEach var="var" items="<%= foreach.array %>">
  <td><%= var %></td>
</ash:forEach>
</tr></table>

<h2>Collection(Vector)</h2>

<table border="2"><tr>
<ash:forEach var="var" items="<%= foreach.collection %>">
  <td><%= var %></td>
</ash:forEach>
</tr></table>

<h2>Iterator</h2>

<table border="2"><tr>
<ash:forEach var="var" items="<%= foreach.iterator %>">
  <td><%= var %></td>
</ash:forEach>
</tr></table>

</body>
</html>

forEachカスタムタグテスト用データクラスのソース(ForEachData.java)

 データクラスでは、各種繰り返しデータの設定を行います。

ForEachData.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.util.*;

/** forEach繰り返しデータ **/
public class ForEachData {
  /** Array型データ **/
  public String[] array;
  /** Collection型データ **/
  public Vector collection;
  /** Iterator型データ **/
  public Iterator iterator;

  ForEachData() {
    // Array型データの作成
    array = new String[] {"data01", "data02", "data03"};

    // Collection型への変換
    collection = new Vector();
    for (int i = 0; i < array.length; i++) {
      collection.add(array[i]);
    }

    // Iterator型への変換
    iterator = collection.iterator();
  }
}

forEachカスタムタグテスト用サーブレットのソース(ForEachServlet.java)

 forEachカスタムタグテストの制御用のサーブレットを作成します。

ForEachServlet.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** forEach繰り返し表示サーブレット **/
public class ForEachServlet extends HttpServlet {
  public void service (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {

    // ForEachオブジェクトの作成
    foreach = new ForEachData();
    req.setAttribute("foreach", foreach);

    // 画面の表示
    req.getRequestDispatcher("ForEach/ForEach.jsp").forward(req, res);
  }
}

forカスタムタグ

forカスタムタグの仕様

 forカスタムタグは、回数を指定して、繰り返し処理を行います。
 変数の値を開始値から終了値を越えるまで、増分値だけ増加させながら処理します。 増分値に負の数は指定できません。
 配列を繰り返す場合は、配列サイズを指定することもできます。

<ash:for var="変数名" begin="開始値" end="終了値" step="増分値" length="配列サイズ">
  <%=変数名%>を使ったJSPの記述
</ash:for>

タグハンドラのソース(ForTag.java)

 タグハンドラは、doStartTag、doAfterBodyメソッドを実装します。

ForTag.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.util.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

/**
 * for繰り返し表示タグライブラリ
**/
public class ForTag extends TagSupport {
  /** カウンタ変数名 **/
  private String var;
  /** カウンタクラス名 **/
  private int begin = 0;
  /** カウンタ終了値 **/
  private int end = -1;
  /** カウンタ増分値 **/
  private int step = 1;
  /** カウンタ値 **/
  private int count;

  /** varの設定 **/
  public void setVar(String var) {
    this.var = var;
  }
  /** beginの設定 **/
  public void setBegin(int begin) {
    this.begin = begin;
  }
  /** endの設定 **/
  public void setEnd(int end) {
    this.end = end;
  }
  /** stepの設定 **/
  public void setStep(int step) {
    this.step = step;
  }
  /** lengthの設定 **/
  public void setLength(int length) {
    this.end = length - 1;
  }

  /** タグ初期処理 **/
  public int doStartTag() throws JspException {
    // データがない場合は処理しない
    if (var == null) {
      return SKIP_BODY;
    }

    // カウンタの設定
    count = begin;
    pageContext.setAttribute(var, new Integer(count));

    // 終了判定
    if (end < count) {
      return SKIP_BODY;
    } else {
      return EVAL_BODY_INCLUDE;
    }
  }

  /** BODYタグ後処理 **/
  public int doAfterBody() throws JspException {
    // データがない場合は処理しない
    if (var == null) {
      return SKIP_BODY;
    }

    // カウンタの設定
    count = count + step;
    pageContext.setAttribute(var, new Integer(count));

    // 終了判定
    if (end < count) {
      return SKIP_BODY;
    } else {
      return EVAL_BODY_AGAIN;
    }
  }
}

タグ拡張情報のソース(ForTEI.java)

 タグ拡張情報では、設定する変数名(var)を定義します。

ForTEI.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import javax.servlet.jsp.tagext.*;

/**
 * forタグライブラリの変数定義
**/
public class ForTEI extends TagExtraInfo {
  public VariableInfo[] getVariableInfo(TagData tagData) {
    String varName = tagData.getAttributeString("var");
    String varType = "java.lang.Integer";

    return new VariableInfo[] {
      new VariableInfo(varName, varType, true, VariableInfo.NESTED)
    };
  }
}

forカスタムタグのテスト

forカスタムタグテスト用画面イメージ

 JSPで、繰り返し型のインデックスで、配列の内容を表示します。 以下に、この画面を表示するためのサンプルソースを示しています。

forタグのテスト×
forタグのテスト
Array(begin、end指定)
1data01
2data02
3data03
Array(step指定)
0data00
2data02
4data04
Array(length指定)
0data00
1data01
2data02
3data03
4data04

forカスタムタグテスト用JSPのソース(For.jsp)

 JSPでforカスタムタグを利用したサンプルです。

For.jsp
<%@ page contentType="text/html; charset=Shift_JIS" %>
<%@ taglib prefix="ash" uri="http://ash.jp/taglib_1_0" %>
<jsp:useBean id="fordata" class="jp.ash.taglib.ForData" scope="request" />

<html>
<head><title>forタグのテスト</title></head>
<body>

<h1>forタグのテスト</h1>

<h2>Array(begin、end指定)</h2>

<table border="2">
<ash:for var="idx" begin="1" end="3">
  <tr>
    <td><%= idx %></td>
    <td><%= fordata.array[idx.intValue()] %></td>
  </tr>
</ash:for>
</table>

<h2>Array(step指定)</h2>

<table border="2">
<ash:for var="idx" begin="0" end="4" step="2">
  <tr>
    <td><%= idx %></td>
    <td><%= fordata.array[idx.intValue()] %></td>
  </tr>
</ash:for>
</table>

<h2>Array(length指定)</h2>

<table border="2">
<ash:for var="idx" length="<%= fordata.array.length %>">
  <tr>
    <td><%= idx %></td>
    <td><%= fordata.array[idx.intValue()] %></td>
  </tr>
</ash:for>
</table>

</body>
</html>

forカスタムタグテスト用データクラスのソース(ForData.java)

 forカスタムタグテスト用データクラスでは、各種繰り返しデータの設定を行います。

ForData.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.util.*;

/** for繰り返しデータ **/
public class ForData {
  /** Array型データ **/
  public String[] array;

  ForData() {
    // Array型データの作成
    array = new String[] {
      "data00", "data01", "data02", "data03", "data04"
    };
  }
}

forカスタムタグテスト用サーブレットのソース(ForServlet.java)

 forカスタムタグテストの制御用のサーブレットを作成します。

ForServlet.java
// Copyright (C)1995-2002 ASH multimedia lab. http://ash.jp/
package jp.ash.taglib;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** for繰り返し表示サーブレット **/
public class ForServlet extends HttpServlet {
  public void service (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {

    // Forオブジェクトの作成
    fordata = new ForData();
    req.setAttribute("fordata", fordata);

    // 画面の表示
    req.getRequestDispatcher("For/For.jsp").forward(req, res);
  }
}

カスタムタグの登録方法

タグライブラリ記述子(taglib.tld)の作成

 タグライブラリの情報をタグライブラリ記述子に設定します。

taglib.tld
<?xml version="1.0" encoding="Shift_JIS" ?>
<!DOCTYPE taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
  "http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>1.2</jsp-version>
  <short-name>ash</short-name>
  <uri>http://ash.jp/taglib_1_0</uri>
  <description>ASHのタグライブラリ</description>

  <tag>
    <name>forEach</name>
    <tag-class>jp.ash.taglib.ForEachTag</tag-class>
    <tei-class>jp.ash.taglib.ForEachTEI</tei-class>
    <body-content>JSP</body-content>
    <description>forEach繰り返しタグライブラリ</description>
    <attribute>
      <name>var</name>
      <required>true</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <name>type</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <name>items</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.lang.Object</type>
    </attribute>
  </tag>

  <tag>
    <name>for</name>
    <tag-class>jp.ash.taglib.ForTag</tag-class>
    <tei-class>jp.ash.taglib.ForTEI</tei-class>
    <body-content>JSP</body-content>
    <description>for繰り返しタグライブラリ</description>
    <attribute>
      <name>var</name>
      <required>true</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
    <attribute>
      <name>begin</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
    <attribute>
      <name>end</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
    <attribute>
      <name>step</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
    <attribute>
      <name>length</name>
      <required>false</required>
      <rtexprvalue>true</rtexprvalue>
      <type>int</type>
    </attribute>
  </tag>

</taglib>

デプロイメント記述子(web.xml)の作成

 タグライブラリ記述子をデプロイメント記述子に設定します。

web.xml
<?xml version="1.0" ?>
<!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>

  <taglib>
    <taglib-uri>http://ash.jp/taglib_1_0</taglib-uri>
    <taglib-location>/WEB-INF/taglib.tld</taglib-location>
  </taglib>

</web-app>


Copyright (C)1995-2002 ASH multimedia lab.
mail : info@ash.jp