□技術メモ - JAVA JSP(詳細) ※管理人の個人的な技術メモです。このページの内容の実行結果について 管理人はいかなる責任も負いかねますのでご自身の責任でお試しください。 ----------------------------------------------------------- ○JSPのタグ (1) コメント 書式: <%-- 〜 --%> (2) JSPディレクティブ 書式: <%@ ディレクティブ名 属性1="AAA" 属性2="BBB"... %> 以下の3つが存在する。 page JSPページの属性設定 書式: <%@page 〜 %> include 外部ファイルの内容をプリコンパイル時に取り込む 書式: <%@include 〜 %> taglib タグライブラリの設定 書式: <%@taglib 〜 %> (3) EL式(Expression Language) 書式: ${式} オブジェクトを参照するときの書式は以下の通り。 ${スコープ名(省略可).オブジェクト名.プロパティ名} (4) 宣言 書式: <%! 〜 %> 宣言タグ内で宣言された変数は1度しか初期化されず、Tomcatが再起動されるまで領域が保持される。 (5) スクリプトレット 書式: <% 〜 %> この範囲でjavaのコードを記述できる。 ここで変数を宣言した場合は毎回初期化される。 処理がスコープの範囲外に移った時に変数は破棄される。 (6) 式 書式: <%= 〜 %> 数式や戻り値のあるメソッドを記述する (7) アクション 書式: , など ※注意 ・宣言、スクリプトレットはセミコロンを付ける。 ・式はセミコロン不要。 ・アクションは閉じるタグが必要。 ○JSP実行時の処理について ・JSPのファイル名がindex.jspの場合は、urlでjspファイルのあるパスまでを指定すれば、index.jspを優先して実行する。 また、ファイル名やパスを変更した場合でも、再ロードや、tomcatの再起動は必要ない。 初回実行時も、コンテキスト名.xmlとjspの配置が正しければ、再ロード等することなくブラウザでurlを指定して表示できる。 ・JSPが実行されると、以下のパスでservletに変換→classファイル作成を経て実行される。 Tomcat\work\Catalina\localhost\コンテキスト名\org\apache\jsp ○pageディレクティブ ・JSPの先頭に以下のようなコードがある。これをpageディレクティブと呼ぶ。 <%@ page language="java" // 使用する言語 contentType="text/html;charset=Windows-31J" // MIMEタイプ コンテンツを出力する際のエンコード pageEncoding="Windows-31J"%> // JSPファイルの文字コード ・主な項目は以下の通り。 language :現状でjava以外指定できない。デフォルトは「java」 extends :JSPページを他のクラスからの継承にしたい場合に指定する。サーブレットへの変換時に使用する。 指定することはあまりない。 import :以下のクラスはデフォルトでインポートしているため記述は不要。 java.lang.* javax.servlet.* javax.servlet.jsp.* javax.servlet.http.* :複数件を1行に書く場合はカンマ区切りにする。 <%@ page import="java.util.Date,java.io.*" %> session :セッションを有効にするか。デフォルトは「true」 buffer :JSPページから出力されるデータのバッファサイズ。noneならバッファなし。デフォルトは「8kb」 autoFlush :バッファを超える出力があった場合の処理。falseなら超過した時にエラーになる。 trueならいっぱいになった時点でクライアントにデータ送信する。デフォルトは「true」 isThreadSafe :trueならスレッドセーフ(複数スレッドの同時実行)する。falseならrequestの到着順に実行。 info :JSPページに関する任意の情報を記述する。avax.servlet.ServletのgetServletInfoで返す値。 errorPage :エラーが発生した場合に表示するページへのパス。指定しない場合はデフォルトのエラーページを表示。 isErrorPage :このページがエラー表示用ページか。trueの場合はexceptionオブジェクトが使用可能になる。 contentType :MIMEタイプを記載する。デフォルトは「text/html;charset=ISO-8859-1」。Latin-1なので日本語は文字化けする。 pageEncoding :JSPページの文字コード。指定しなければcontentTypeのcharsetと同じ。 isElIgnored :EL式を無効にするか。デフォルトは「false」(有効) ○includeディレクティブ ・JSPの文中に以下のようなコードを記述できる。これをincludeディレクティブと呼ぶ。 <%@ include file="/path" %> <%-- /から始まるパスは、ドキュメントルートからのパス --%> <%@ include file="../path" %> <%-- /以外から始まるパスは、現在のjspからの相対パス --%> ・includeにはJSP, HTML, TEXTを指定することが可能。pageディレクティブを除いた部分がincludeされる。 ・画像ファイルやservletをincludeしてもコンパイラは理解できないのでエラーになる。 ・JSP間で循環参照が起きている場合にもエラーになる。 ・bmpファイルを参照しているhtmlは、ローカルで開くと画像が表示されるが、tomcat経由だと表示できない。 したがってJSPでincludeしている場合も、bmpを参照しているhtmlは画像を表示できない。 ・include側に値を渡す場合、setAttribute, getAttributeで渡す。もしくはコード経由で渡す。 使用する変数を揃えたい場合などはコード経由が良いかも知れない。状況に応じて適切な方法を選択する。 ・との違いは、<%@ include>が実行前にincludeされるのに対して、は実行結果を動的に返すことにある。 importなどを揃えたい場合は<%@ include>, 条件によって表示を変えたい場合などはが良いかもしれない。 ・----文字化け対策についての考察(2015/02/13記) ・<%@ include> は文字化けが発生しやすい。文字コードについて正しく理解することが必要になる。 ・(予備知識)contentTypeのcharsetはコンテンツ出力時の文字コード指定。pageEncodingはファイル保存時の文字コードをコンテナに伝える。 pageディレクティブでpageEncodingの指定がない場合はcontentTypeのcharsetがファイル読み込み時に使用される。 ・(予備知識)Java仮想マシン内部では全ての文字列はunicodeで表現される。したがってサーブレット・コンテナは、 pageEncodingの文字コード→unicode→contentTypeのcharsetという変換を行っている。 ・(予備知識)WindowsにおけるJavaのデフォルトエンコーディングはMS932,つまりwinsows-j31。 ・JVM内ではunicode統一なのだから、pageEncodingとファイル保存時のエンコードが一致していれば、JVMは正しくunicodeに変換して読み込むことができる。 以下、pageEncodingと、ファイル保存時のエンコードは一致していることを前提とする。 ・----<%@ include>の文字化け対策 ・contentTypeの文字コードが、親側とinclude側で揃ってない場合「contentTypeを異なる値で複数回指定するのは無効です」と表示されてエラーとなる。 <%@ include>の場合、生成されるクラスファイルは1つなのでcontentTypeが異なる場合はエラーとなる。 コンテンツ出力時の文字コードは統一する必要があり、親側で指定する。 ・<%@ include>で非JSPを読み込むと、日本語が文字化けする。これは<%@ include>の場合、 TEXTやHTMLはpageディレクティブがないため文字コードの判定ができず、 include側の非JSPファイルは常にISO-8859-1(Latin1)で読み込むという制限があるのが原因らしい。 日本語を文字参照にしてLatin1にすればいいのではないかと思うがどうもうまくいかない。 確認のため、UTF-8とwindows-31jで考えれる組み合わせについて日本語の文字化けの確認を行った。結果はHTMLとTEXTは全滅。JSPは全てOK。 日本語を含む場合はやはりJSPに変換してpageディレクティブを付ける必要があると思われる。 ・----の文字化け対策 ・の場合も上記と同じ様にUTF-8とwindows-31jで考えれる組み合わせについて日本語の文字化けの確認を行った。 結果はJSPは全てOK。HTMLとTEXTは親側のcontentTypeのcharsetに関係なく、pageEncodingがwindows-31jならOK、UTF-8ならNGとなった。 ・classファイルは親側とinclude側で別々に作成されるが、contentTypeの文字コードが食い違っていても正常に表示される。 つまり表示の際はcharsetの混在は可能だと考えられる。 ・非JSPファイルはpageディレクティブがないため文字コードの判定ができず、Windowsにおけるデフォルトエンコードであるwindows-31jを 使用すると思われる。従ってpageEncodingがWindows-31Jの時のみ読み込みが正常に行われ、 Windows-31J以外の場合は読み込みの時点で既に文字化けが起きていると思われる。 ・結論としては、で日本語を含むファイルを取り込む場合、JSPなら問題は発生せず、 HTMLはpageEncodingをwindows-31j、TEXTは保存時の文字コードがwindows-31jなら良い、となる。 ※動作確認結果 (準備中) -------->この範囲は推測を多く含みます。 <%@ include> ・JSPの場合、コンテナはファイルを正しく読み込んでunicodeに変換するので問題は起きない。 ・TEXT,HTMLの場合、pageディレクティブがないためコンテナは文字コードを判定できず、Latin1で読み込む。 Latin1は日本語を扱えないので、日本語を扱う場合はpageディレクティブ付きのJSPに変換が必要になる。 ・JSPの場合、コンテナはファイルを正しく読み込んでunicodeに変換する。複数のクラスファイルがそれぞれのcontentTypeの文字コードで画面出力を行うが、 文字化けは発生しないので、表示の際は複数の文字コードの混在が可能と思われる。 ・TEXT,HTMLの場合、pageディレクティブがないためコンテナは文字コードを判定できず、windowsのデフォルトエンコードのwindows-j31で読み込む。 ファイル保存時の文字コードがwindows-j31なら問題がないが、それだとunicode文字を扱うことができない。 unicode文字を扱う必要がある場合はpageディレクティブ付きのJSPに変換して、contentTypeのcharsetとpageEncodingをUTF-8に指定する必要がある。 <-------- ○taglibディレクティブ (保留) ○EL式(Expression Language) ・書式は${式}。{}で囲まれた式の計算結果を返す。 ・オブジェクトにアクセスする場合の書式 ${スコープ名(省略可).オブジェクト名.プロパティ名} ただし、オブジェクトに対してgetXXXX(プロパティ名)メソッドが定義されていることが必要。 ・配列やListにアクセスする場合の書式 ${スコープ名(省略可).オブジェクト名[index]} ・Mapにアクセスする場合の書式 ${スコープ名(省略可).オブジェクト名[key]} ・スコープ名は以下のいずれかを指定する。 sessionScope applicationScope requestScope pageScope ・EL式における暗黙のobjectは以下の通り (1) request 書式:request.キー (2) session 書式:session.キー (3) application 書式:application.キー (4) page 書式:page.キー ※注意 : EL式でキーのみ指定した場合は以下の優先順位で検索される。 スコープを検索する順番 page→request→session→application (5) pageContext 書式:pageContext.(context|session|request).xxxx ・記述例: pageContext.session.id; //セッションID pageContext.request.method; //Requestメソッド pageContext.request.contextPath //コンテキストパス (6) cookie 書式:cookie.param名.value (7) initParam 書式:initParam.param名 web.xmlにおける初期化パラメータを取得する ・servlet単位の初期値を取得する config.getInitParameter(param) getServletConfig().getInitParameter(param) ・context単位の初期値を取得する (EL式) initParam.パラメータ名 application.getInitParameter(param) ・EL式の initParam.パラメータ名 は、メソッド名からを取得するような気がするが、 Tomcat 8.0ではcontext単位の初期値を取得する(2015/02/12記)。 これが正しい仕様なのかは不明。気を付けること。 (8) Param(単数), paramValues(複数) 書式:Param.Param名, paramValues.Param名[i](0から始まる添え字) (9) Header(単数), HeaderValues(複数) 書式:Header.キー, HeaderValues.キー[i](0から始まる添え字) ○アクションタグ ・書式 ---- ---- ---- ・書式 も同様。 ・pathはcontextルートからの相対パス。 ・はinclude側の出力結果を動的に取り込む。 ・は指定したファイルに処理を転送したまま戻ってこない。 forwardの前に出力があると例外がスローされるので注意。 ○暗黙のオブジェクト ・JSPでは宣言なしで使用できる暗黙のオブジェクトが存在する。以下の9つ。 ・EL式における暗黙のオブジェクトとは顔ぶれが違うので気を付けること。 request, session, application, page, pageContext, ---->以下のオブジェクトはEL式にはない response, config, out, exception <---- ○requestで使用可能な主要メソッド Enumeration getHeaderNames() String getHeader(String) Enumeration getHeaders(String) Enumeration getParameterNames() String getParameter(String) Enumeration getParameterValues(String) Cookie[] getCookies() String getMethod( ) void setCharacterEncoding(String) ○responseで使用可能な主要メソッド void addHeader(String, String) void addDateHeader(String, long) //1970年1月1日からの経過時間をミリ秒で指定 void addintHeader(String, int) void setHeader(String, String) void setDateHeader(String, long) //1970年1月1日からの経過時間をミリ秒で指定 void setintHeader(String, int) void addCookie(Cookie) //Clientに返すCookieオブジェクトを追加する void sendError(int) //HTTPプロトコルのエラーステータスを返す void sendError(int, msg) //メッセージ付きのエラーステータスを返す void setStatus(int) //エラーでない時のステータスを返す void setStatus(int, msg) //メッセージ付きのステータスを返す。非推奨。sendError(int, msg)を使用すること。 String encodeURL(String) //指定のURLに、セッションIDを付与したURLを生成する。 String encodeRedirectURL(String) //リダイレクトするURLに、セッションIDを付与したURLを生成する。 (※注意)上記2つのメソッドでは セッションIDを付与する必要がない場合(Cookieを使用できるなど)ではURLは変化しないことに注意。 (※注意)上記2つのメソッド以外に、encodeUrl, encodeRedirectUrl があるが、いずれも推奨されていないので注意。 void sendRedirect(String) //指定のURLへリダイレクトを行う。 ○sessionで使用可能な主要メソッド Enumeration getAttributeNames() Object getAttribute(String) void setAttribute(String, Object) void removeAttribute(String) int getMaxInactiveInterval() //セッション保持時間(秒) void setMaxInactiveInterval(int) ServletContext getServletContext() //セッションが属しているServletContextを返す String getId() //一意のセッションIDを返す void invalidate() //セッションIDを破棄 boolean isNew() //クライアントがセッション管理されてないならtrue ・web.xmlにてセッション保持時間を設定する。 , の後に記述すること。 -------- 60 //60秒 -------- ○セッションIDは以下の場合に削除される。 規定の時間が経過する。(Tomcatのデフォルトは30分) クライアントのブラウザを閉じる。 invalidate()を呼び出す。 ○applicationで使用可能な主要メソッド Enumeration getAttributeNames() //applicationスコープで利用可能なすべてのデータ名 Object getAttribute(String) void setAttribute(String, Object) void removeAttribute(String) Enumeration getInitParameterNames() //すべてのパラメータ名 String getInitParameter(String) void log(String) //log出力 String getServerInfo() //サーブレットコンテナの名前とバージョン String getRealPath(String) //相対パスを絶対パスに変換 例:/index.html → http://localhost/コンテキスト名/index.html ・web.xmlにてコンテキストの初期化パラメータを設定する。 getInitParameter(param)にて取得する。 -------- iniNm1 //パラメータ名 Value1 //値 --------