スクリプト変数の使用

スクリプト変数は、ユーザーがページをリクエストするときに JSP で使用できる変数です。宣言、スクリプトレット、または式の中のスクリプト変数にアクセスできます。

カスタムタグでスクリプト変数を定義できます。スクリプト変数は、JSP 内のスクリプトレットや他のカスタムタグで使用できます。スクリプト変数は、JSP の pageContext オブジェクトにオブジェクトとして保管されます。その結果、スクリプト変数を Strings および Integers として設定できるだけでなく、データベース接続または他の直列化可能なオブジェクトとしても設定できます。

カスタムタグにスクリプト変数を設定するには、2 つの方法があります。

どちらの方法でも、JSP でカスタムタグスクリプト変数を使用可能にできますが、JSP 1.2 の方法の方が簡単に実装できます。ただし、多くの既存のカスタムタグライブラリでは JSP 1.1 の方法を使用しているので、JSP 1.1 の方が柔軟性はあります。

このセクションでは、カスタムタグ内でスクリプト変数を使用する 2 つの方法を説明します。

メモ:  タグ属性 (ID 属性など) を使用してスクリプト変数を定義できますが、タグ属性とスクリプト変数は直接は関係ありません。

JSP 1.2 でのスクリプト変数の使用

JSP 1.2 では、JSP ページのカスタムタグのスクリプト変数を使用する簡単な方法を導入しています。次のタスクを実行する必要があります。

次のセクションでは、これらのタスクについて説明します。

タグハンドラでのスクリプト変数の有効化

タグハンドラは pageContext オブジェクトにスクリプト変数を追加します。タグハンドラでは、スクリプト変数に指定されているスコープに応じて、これらの変数をさまざまな方法で定義します。さらに、本文テキストをループ処理するタグハンドラでは、doAfterBody メソッドによって、スクリプト変数を更新またはリセットできます。

次の例は、タグハンドラがスクリプト変数を設定する方法を示しています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;
public class HelloTag extends BodyTagSupport {
  String to;
public void setTo(String to) {
  this.to = to;
}
public int doStartTag() throws JspException {
  try {
    pageContext.getOut().print("Hello " + to);
    // AT_BEGIN として定義されるので、ここで定義します。 
    // doInitBody 内で定義し、ループの場合は 
    // doAfterBody 内で変更またはリセットできます。
    pageContext.setAttribute("foo", "foo");
    return EVAL_BODY_INCLUDE;
  } catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}
public void doInitBody() throws JspException {
  // NESTED として定義されるので、ここで定義します。 
  // doStartTag 内で定義し、ループの場合は 
  // doAfterBody 内で変更またはリセットできます。
  pageContext.setAttribute("baz", "baz");
}
public int doEndTag() throws JspException {
  try {
    // このタグハンドラによって BodyTag が実装されるので 
    // (BodyTagSupport を拡張することによって)、
    // 本文のライターと元のライターを統合する必要があります。
    pageContext.getOut().print(bodyContent.getString());
    // AT_END として定義されるので、
    // doEndTag まで自分で定義する必要はありません。
    pageContext.setAttribute("bar", "bar");
    return EVAL_PAGE;
  } catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}
}

TLD ファイルでのスクリプト変数の追加

tag 要素の variable サブ要素にスクリプト変数を定義します。次の表で、variable 要素のサブ要素について説明します。
tag のサブ要素
説明
name-given
スクリプト変数名。JSP で変数にアクセスする際に
使用します。
name-from-attribute
スクリプト変数の代替名。変数のトランスレート時に
名前を設定します。
variable-class
オプション。変数の完全修飾クラス。
たとえば、java.lang.Double
デフォルトは java.lang.String です。
declare
オプション。新しい変数を作成するかどうかを決定する Boolean 設定。デフォルトは true です。
scope
スクリプト変数のスコープ。次の 3 つの値のいずれかに設定できます。
  • AT_BEGIN  スコープを AT_BEGIN に設定すると、カスタムタグの本文か、タグの本文の外にあるタグの後の JSP ページのいずれかで発生する任意の宣言、式、またはスクリプトレットでスクリプト変数を使用可能にできます。
  • AT_END  スコープを AT_END に設定すると、カスタムタグの後の JSP で発生する任意の宣言、式、またはスクリプトレットでスクリプト変数を使用可能にできます。このタグはタグの本文内では使用できませんが、その後で宣言されます。
  • NESTING  スコープを NESTING に設定すると、JSP 内のカスタムタグの本文でのみスクリプト変数を使用可能にできます。このメソッドによって最少量の
    リソースが使用されます。

次の例は、カスタムタグのスクリプト変数を定義する TLD ファイルを示しています。

<?xml version="1.0" ?>
<taglib>
...
  <tag>
...
    <variable>
      <name-given>foo</name-given>
      <name-from-attribute>foo</name-from-attribute>
      <variable-class>java.lang.String</variable-class>
      <declare>true</declare>
      <scope>AT_BEGIN</scope>
    </variable>
    <variable>
      <name-given>bar</name-given>
      <name-from-attribute>bar</name-from-attribute>
      <variable-class>java.lang.String</variable-class>
      <declare>true</declare>
      <scope>AT_END</scope>
    </variable>
    <variable>
      <name-given>baz</name-given>
      <name-from-attribute>baz</name-from-attribute>
      <variable-class>java.lang.String</variable-class>
      <declare>true</declare>
      <scope>NESTED</scope>
    </variable>
...
  </tag>
</taglib>

JSP 1.1 でのスクリプト変数の使用

JSP 1.1 で JSP ページのカスタムタグのスクリプト変数を使用するには、次のタスクを実行する必要があります。

このセクションで説明した JSP 1.1 の方法でスクリプト変数を使用すれば、TEI クラスを拡張することによってタグを検証できます。このようなタグの検証が不要な場合は、 「JSP 1.2 でのスクリプト変数の使用」 で説明した JSP 1.2 の方法でスクリプト変数を使用します。

TEI クラスのコーディング

カスタムタグでスクリプト変数を作成する場合、Java 開発者は TEI ファイルも作成する必要があります。TEI ファイルは、JSP コードで使用するスクリプト変数とそのスコープを定義する Java クラスです。TEI ファイルを使用して、トランスレート時に属性を検証することもできます。

TEI ファイルは、TagExtraInfo クラスを拡張する Java クラスです。
getVariableInfo メソッドには、次の署名があります。

public VariableInfo[] getVariableInfo(TagData tagData) { }

tagData パラメータには、属性の名前/値のペアが格納されています。この名前/値のペアを使用してスクリプト変数を定義します。たとえば、useBean タグは、id 属性を使用してスクリプト変数を作成します。

getVariableInfo メソッド内で、VariableInfo オブジェクトの配列を作成し、1 つのスクリプト変数につき 1 つの VariableInfo オブジェクトをその配列に挿入します。次の表で、VariableInfo オブジェクトのコンストラクタが取るパラメータについて説明します。
パラメータ
説明
varName
スクリプト変数名を指定する String 型パラメータ。
className
スクリプト変数のクラスを指定する String 型パラメータ。
declare
コンストラクタで新規の変数を宣言するかどうかを指示する Boolean 型パラメータ。
scope
スクリプト変数のスコープを指定する Int 型パラメータ。次の表に示すように AT_BEGINNESTED、または AT_END を指定します。

同期化とは、ページコンテキストからオブジェクトを取り出して、それをスクリプト変数に割り当てる操作です。次の表で、getVariableInfo メソッドで指定した変数に関するスコープ、使用方法、および同期化について説明します。
スコープ
JSP での使用方法
JSP の同期化
設定およびリセット
される場所
AT_BEGIN
タグの本文内と、JSP の残りの部分
このスクリプト変数は、本文を反復するたびに
リセットされます。
doInitBodydoAfterBody (BodyTag を実装している場合)。それ以外の場合は doStartTag または doEndTag
NESTED
タグの本文内
このスクリプト変数は、本文を反復するたびに
リセットされます。
doInitBodydoAfterBody (BodyTag を実装している場合)。それ以外の場合は、doStartTag。
AT_END
JSP の残りの部分
この変数は、本文の実行が完了した後でリセットされます。
doEndTag の後

スクリプト変数の使用例

次の例は、3 つのスクリプト変数を定義する TEI クラスに関する Java コードを示しています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;
public class HelloTEI extends TagExtraInfo {
public VariableInfo[] getVariableInfo(TagData tagData) {
  VariableInfo[] vars = new VariableInfo[3];
  // ページの本文と残りの部分で使用できます。
  vars[0] = new VariableInfo("foo", "java.lang.String", false,
variableInfo.AT_BEGIN);
  // ページの残りの部分のカスタムタグの後ろで使用できます。
  vars[1] = new VariableInfo("bar", "java.lang.String", true,
VariableInfo.AT_END);
  // タグ本文でのみ使用できます。
  vars[2] = new VariableInfo("baz", "java.lang.String", true,
VariableInfo.NESTED);
  return vars;
}
}

次の JSP の例では、TEI クラスで定義したスクリプト変数を使用しています。

<%@ taglib prefix="test" uri="test.tld" %>
<% String foo; %>
<test:hello to="World">
  <%-- baz は NESTED です (本文でのみ使用可能)。--%>
  <%= baz %>
  <%-- foo は AT_BEGIN です (本文とそれ以外でも使用可能)。--%>
  <%= foo %>
</test:hello>
<%= foo %>
<%-- bar は AT_END です (本文の後ろでのみ使用可能)。--%>
<%= bar %>

属性の検証

TEI クラスは、isValid メソッドをオーバーライドしてタグ特有の属性の検証を実施できます。トランスレート時に、JRun から isValid メソッドに TagData インスタンスが渡されます。

isValid メソッドは、TagData.getAttribute を呼び出して、その値にアクセスできます。TLD ファイル内の属性の定義で実行時の式を有効にしている場合は、TagData.REQUEST_
TIME_VALUE
オブジェクトを調べることができます。このオブジェクトは、カスタムタグの呼び出しが実行時の式を使用していることと、検証が不可能であることを示します。実行時の式の詳細については、 「TLD ファイルでの属性の定義」 を参照してください。

次のクラスの例では、バージョン属性の値が 5 より小さいことを確認します。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;
public class TestIsValidTEI extends TagExtraInfo {
  // この例では、スクリプト変数が 1 つであると想定しています 
  // (この例とは無関係)。
public VariableInfo[] getVariableInfo(TagData tagData) {
  VariableInfo[] vars = new VariableInfo[1];
  vars[0] = new VariableInfo("foo", "java.lang.String", true,
VariableInfo.AT_BEGIN);
  return vars;
}
public boolean isValid(TagData data) {
  Object version = data.getAttribute("version");
  // この属性では実行時の式が使用できるので、
  // REQUEST_TIME_VALUE をチェックする必要があります。
  if (version != null && version != TagData.REQUEST_TIME_VALUE) {
    int iVersion = Integer.parseInt((String)version);
    // バージョンは 5 以下です。
    if (iVersion > 5) {
      return false;
    }else {
      return true;
    }
  }else {
    return false;
  }
}
}