S-JIS[2005-09-18/2008-09-09] 変更履歴

JSPディレクティブ・スクリプトレット

jspファイルは、JSPコンテナ内ではJavaのソース(サーブレット)に変換され、コンパイルされて保持される。
この変換されたソース内に、(taglibを使わずに)直接Javaのソースコードを埋め込む方法 がいくつか用意されている。


JSPディレクティブ

そのjspクラスの先頭で、各種宣言をするのに使う。

<%@ ディレクティブ %>


<%@page import="インポートするクラス" %>

<%@ page import="java.util.*,java.math.*" %>

importは、JSPがサーブレットに変換されると そのサーブレットのソースのimport文になる。


<%@page contentType="コンテンツタイプ" %> [2008-08-02]

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

なお、pageディレクティブでは、importとかcontentTypeをひとかたまりで書いてもいいようだ。

<%@ page
	import="java.util.Date"
	contentType="text/html; charset=Shift_JIS"
%>

<%@page pageEncoding="文字コード" %> [2008-09-09]

<%@ page pageEncoding="Windows-31J" %>

そのJSPの文字コード(エンコーディング)を指定する。

contentTypeは生成されるHTMLの<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">に相当するものであり、1つのJSPに複数書くようなものではない。
つまり、他のJSPからincludeされるようなJSPではcontentTypeはふさわしくないので、pageEncodingを使う。


<%@taglib uri="tldファイルの位置" prefix="タグの接頭辞" %>

<%@ taglib uri="/WEB-INF/taglib/hoge.tld" prefix="pre" %>

カスタムタグtldファイルの場所と、JSP内で使用する接頭辞を宣言する。

web.xml経由で指定することも可能


<%@include file="インクルードJSP" %>

<%@ include file="common.jsp" %>

includeディレクティブは、サーブレットへの変換前に、指定されたjspファイルをその位置に展開する。いわばC言語の#includeに相当。

したがって、JSP宣言で宣言された変数を、インクルードしたJSPで使用することも出来る。[2007-08-12]

sample.jsp:

<%! private static final String FORM_NAME = "ZZZ"; %>
<html><body>
<%@ include file="sub.jsp" %>
</body></html>

sub.jsp

<form name="<%= FORM_NAME %>">
〜
</form>

↓生成されるHTML

<html><body>
<form name="ZZZ">
〜
</form>
</body></html>

ただし、事前コンパイルを実施する場合は、インクルードするJSPはコンパイル対象から除外しておかないとエラーになるかもしれない。
(上記の例でいうと、sub.jspのみでコンパイルするとFORM_NAMEがどこにも宣言されていないからコンパイルエラーになる)


JSP宣言

そのjspクラス内のフィールドやメソッドを定義するのに使う。[/2007-08-12]

<%! 宣言 %>

<%!	private static final String NAME = "NAME";
	private static final String VAL  = "VALUE"; %>
<%!	private int count = 0;
	private synchronized int getCount() { return ++count; }
%>

JSPがサーブレットに変換されると、そのサーブレットのクラス内のフィールド変数宣言やメソッド定義になる。
そのため、この変数やメソッドを使う際にはMTセーフとなるように扱わなければならないこの意味が分からない人は、JSP宣言を使うの禁止!

複数のトランザクション間で共有したいデータなんてあまり無い(せいぜいカウンターくらい?)だろうから、定数の宣言くらいに使うのが無難かなぁ。


JSP式

jspクラス内のその位置でJavaの演算(式の実行)を行い、その結果をHTMLとして出力するのに使う。(式言語とは別物)

<%= 式 %>

<%= getCount() %>

JSPがサーブレットに変換されると、「out.print(getCount());」のようなHTML出力になる。
メソッドを呼び出すなら、そのメソッドはサーブレットからの呼び出しとなる為、MTセーフでなければならないこの意味が分からない人は、JSP式を使うの禁止!
変数を出力するだけなら大丈夫なはずだが、見た目が変数出力であっても実際にはメソッドが呼び出される場合もあるので、注意が必要。
適当なクラスCのインスタンスcに対して<%= c %>とすると、out.print(c);に変換される。実際に呼ばれるのはout.print(Object)であり、 この中でc.toString()が使われる。 つまり、ソース上の見た目は変数出力のようであっても、実際はメソッドが呼ばれる。この場合、C#toString()がMTセーフであることを確認しておく必要がある。

また、HTML上に直接出力される文字列となるため、「<」「>」「&」といった文字が出力される可能性を考慮しなければならない。[2007-08-12]
(ユーザーから入力された値を出力するなら、サニタイジングする必要があるだろう。HTMLのタグを出力したいなら、サニタイジングすると変になるだろう。プログラム内でしか生成しない値なら、サニタイジングを気にする必要はないかもしれない)


JSP式言語(JSP EL)

EL(Expression Language:式言語)は、JSP2.0から使えるようになった。[2007-06-17/2007-08-12]
変数の値を出力するのに使う。JSP式他のJSPタグの属性の値に使うには設定が必要なのに対し、ELでは 気にせず使える点が非常に便利。

${ 式 }

${bean.value}
<test:tag attribute="${bean.value}" />

その他、演算も書ける。


スクリプトレット

jspクラス内のその位置でJavaの文を実行するのに使う。→使用例

<% 文 %>

<% out.println("hoge"); %>

サーブレットのメソッド内のソースを自由に書けるので、MTセーフとなるよう注意しなければならないこの意味が分からない人は、スクリプトレットを使うの禁止!


JSPコメント

jspファイル内にコメントを書くのに使う。[2007-06-17]

<%-- コメント --%>

<%-- comment --%>

このコメントはjspファイル内のコメントなので、最終的に生成されるHTML上には残らない。(変換されたjavaソースにも書かれなさそう)
<!-- コメント -->」はHTMLのコメントなので、jspファイル内に書くと 生成されるHTMLに出力される。

スクリプトレットを使って「<%// comment %>」と書けば、変換されたjavaソースにもコメントとして残る。[2007-09-02]


暗黙の変数

基本的に、上述のスクリプトレットJSP式の方法は、JSPコンテナ内で変換されたJavaソースに ソースコードを埋め込むだけ。
したがって、暗黙に宣言された変数を使うことも出来るし、整合性のとれない文を書くとJavaのコンパイルエラーになる。

変数名 概要 使用例
pageContext もろもろの基本情報 javax.servlet.jsp.PageContext  
page 現在のJSP(サーブレット)インスタンス    
request HTTPリクエスト javax.servlet.http.HttpServletRequest <%= request.getParameter("name") %>
response HTTPレスポンス    
session HTTPセッション javax.servlet.http.HttpSession <% Integer value=(Integer)session.getAttribute("name"); %>
application Webアプリケーション javax.servlet.ServletContext <% String value=(String)application.getAttribute("name") %>
config ServletConfig javax.servlet.ServletConfig <%= config.getInitParameter("name") %>
out HTML出力先   <% out.print("hoge"); %>
<% out.println("hage"); %>

それぞれのスコープに入っている属性をHTMLに出力する例

test.jsp:

<p>pageContext:<br/>
<%
	int[] scope_arr = new int[]{
		PageContext.PAGE_SCOPE,      	//1
		PageContext.REQUEST_SCOPE,   	//2
		PageContext.SESSION_SCOPE,   	//3
		PageContext.APPLICATION_SCOPE	//4
	};
	for(int i=0; i<scope_arr.length; i++) {
		int scope = scope_arr[i];
		Enumeration e = pageContext.getAttributeNamesInScope(scope);
		while(e.hasMoreElements()) {
			String name = (String)e.nextElement();
			out.println(scope + ":" + name + ":" + pageContext.getAttribute(name, scope) + "<br>");
		}
	}
%>
</p>

requestに入っている属性をHTMLに出力する例

test.jsp:

<p>request:<br/>
<%
	Enumeration e = request.getParameterNames();
	while(e.hasMoreElements()) {
		String name = (String)e.nextElement();
		out.println(name + ":" + request.getParameter(name) + "<br>");
	}
%>
</p>

実行してみると分かるけど、pageContextのREQUEST_SCOPEに入っている属性requestに入っている属性は異なる。
requestに入っているのは HTTPリクエストとして サブミット元のHTMLのフォームに入っていた情報で、
pageContextのREQUEST_SCOPEに入っているのは、それを元にJSPエンジンが作った情報(例えばStrutsが作り出したActionFormのインスタンス等)っぽい。

→Strutsのlogic:iterateのスコープ


参考


JSPへ戻る / Javaへ戻る
メールの送信先:ひしだま