jspファイルは、JSPコンテナ内ではJavaのソース(サーブレット)に変換され、コンパイルされて保持される。
この変換されたソース内に、(taglibを使わずに)直接Javaのソースコードを埋め込む方法
がいくつか用意されている。
その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>
<form name="<%= FORM_NAME %>"> 〜 </form>
↓生成されるHTML
<html><body>
<form name="ZZZ">
〜
</form>
</body></html>
ただし、事前コンパイルを実施する場合は、インクルードするJSPはコンパイル対象から除外しておかないとエラーになるかもしれない。
(上記の例でいうと、sub.jspのみでコンパイルするとFORM_NAMEがどこにも宣言されていないからコンパイルエラーになる)
その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クラス内のその位置で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のタグを出力したいなら、サニタイジングすると変になるだろう。プログラム内でしか生成しない値なら、サニタイジングを気にする必要はないかもしれない)
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ファイル内にコメントを書くのに使う。[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"); %> |
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>
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のスコープ