JSP (Jakarta Server Pages)

JSP (Jakarta Server Pages、旧JavaServer Pages) とは、Javaプログラムを埋め込んだHTMLから自動的にJavaサーブレットを生成できる仕組みです。

JSPとは

JSP (JavaServer Pages) は Java サーブレットのように動的にページを作成できます。 サーブレットと異なり、HTML とクラスファイルが分かれておらず、ひとつのファイル (*.jsp) になっています。 JSP は実際のところ、JSPコンテナが自動的にサーブレットを生成してくれるだけです。

JSP
Figure 1. JSP

application

application は javax.servlet.ServletContext クラスのオブジェクトで、JSP において宣言しなくても使える特別なオブジェクトである。これをサーブレット内で取得しようとするとgetServletConfig().getServletContext()などとしなければならないが、JSPではこのようにあらかじめ用意されています。

config

config は javax.servlet.ServletConfig クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

configはサーブレット内ではgetServletConfig()などとして取得しなければなりませんが、applicationと同様にJSPではあらかじめ用意されています。初期設定パラメータを取得するのに使用します。

exception

exception は javax.lang.Throwable クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

out

out は javax.servlet.jsp.JspWriter クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

outはクライアント(ユーザのブラウザ画面)への出力ストリームを表しており、print(), println()メソッドでHTMLタグなどを送信するのに使用します。

out.print()メソッドとout.println()メソッドの違いは、改行をするかしないかの点です。ただし、その改行とはCR+LFのことであって、<br>タグのことではありません。

page

page は javax.lang.Object クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

pageContext

pageContext は javax.servlet.jsp.PageContext クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

request

request は javax.servlet.ServletRequest クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

クライアントから受信したパラメータやデータを送信してきたクライアントのIPアドレスなどを取り出すことができます。

requestオブジェクトが持つメソッドのうち、最もよく使われるであろうgetParameter()メソッドですが、これはひとつのパラメータを取り出します。しかし、checkboxを使用する場合は、名前はひとつでも複数の値を送信してきます。そんなときにはgetParameterValues()メソッドを使用します。

requestオブジェクトの使用例を次に示します。

if (request.getParameter("reset") != null) {
  counter.reset();
}

response

responseはjavax.servlet.ServletResponseのサブクラスなのですが、実際にはHttpServletResponseのメソッドが使用できます。クライアント(ユーザのブラウザ画面)に送信すべきtext/htmlなどのデータをセットするのに使用できます。

session

session は javax.servlet.http.HttpSession クラスのオブジェクトであり、JSP において宣言しなくても使える特別なオブジェクトである。

クライアントに接続していることを示すためのセッションIDを保持しています。クライアントが接続している間はページの間をまたがってオブジェクトを保持させておくことができます。

JSTL Functions

fn:contains()

文字列の中に部分文字列が含まれているかどうかを返す。

fn:contains(string, substring)

fn:containsIgnoreCase()

文字列の中に部分文字列が含まれているかどうかを返す。比較の際、大文字と小文字は区別しない。

fn:containsIgnoreCase(string, substring)

fn:endsWith()

指定した文字列で終わるかどうかを返す。

fn:endsWith(string, suffix)

fn:escapeXml()

文字列に含まれるXML予約文字をエスケープする。

fn:indexOf(string, substring)

fn:indexOf()

部分文字列が出現する位置を返す。

fn:indexOf(string, substring)

fn:join()

配列の各要素を連結して文字列として返す。

fn:join(array, separator)

fn:length()

コレクションの項目数又は文字列の文字数を返す。

fn:length(object)

fn:replace()

文字列を置き換える。

fn:replace(string, before, after)

fn:split()

文字列を分割して配列で返す。

fn:split(string, separator)

fn:startsWith()

指定した文字列で始まるかどうかを返す。

fn:startsWith(string, prefix)

fn:substring()

部分文字列を返す。

fn:substring(string, start, end)

fn:substringAfter()

指定文字列以降の文字列を返す。

fn:substringAfter(string, substring)

fn:substringBefore()

指定文字列以前の文字列を返す。

fn:substringBefore(string, substring)

特殊文字のエスケープ

JSPページ内で「<%」をtemplateに書きたければ「<\%」と書きます。

JSPページ内で「%>」をtemplateに書きたければ「\%>」と書きます。

「"」や「'」をtemplateに書きたければ「\"」や「\'」と書きます。

Servletの問題点

HTMLを生成するサーブレットプログラムを書くと、HTMLタグを出力するprintメソッドが連なったコーディングになってしまいます。これでは最終的に生成されるHTMLを想像しづらくなります。それに、画面生成プログラムを各場合には、まずHTMLで画面設計をして、それをJavaプログラム中のprintメソッドにいちいち置き換えていくという作業となります。これは2度手間になります。

また、画面の変更が大仕事になるという点にも問題があります。Webの画面を変更したいという要求は頻繁に発生するでしょう。しかし、本番稼動中のServletプログラムには手を入れたくない場合もあります。結局、HTMLは直らず魅力が無いWebページが残りつづけるということになりかねません。

なお、こうした問題はCGIプログラムを各場合でもまったく同様です。

これらの問題を解決する技術として登場したのがJSPです。HTMLファイルの中にJavaコードを含めることができます。この点はASP (Active Server Pages)と似ています。

ServletだけでHTMLファイルを生成すると・・・

問題1:プログラムコードのあちこちでHTML生成用のprintメソッドを呼び出すため、最終的なHTMLファイルを想像しづらい。

問題2:HTMLファイル(出力画面)を手作業でprintメソッドに書き直すことになり、手間が増える。

問題3:出力画面を変更するのにServletのコード修正が必要

解決策:プレゼンテーション部分をJSPとして分離する。

JSPのスクリプト(Scriptlet)だけでロジックを記述しようとすると・・・

→ServletからJSPを呼び出す。ロジックはServlet、プレゼンテーションはJSPと分離する。

JSPではJavaによるスクリプト「Scriptletを記述できる。ちょっとしたプログラムを組んだWebページを作ることも可能である。

ただJSPだけでプログラムを作ろうとすると、やはり問題が出てくる。Scriptletの間でデータ交換したり、複数のscriptletを並行動作させるといった使い方はJSPだけでは実現しづらい。

ちょっとしたWebプログラムであれば、JSPだけでも作成可能だが、本格的なシステム構築ではServletとJSPを組み合わせて利用することが望ましい。

ASPとJSPの違いは

  1. Visual Basicだけでなく、Javaによるプログラムを記述できる
  2. 複数のWebアプリケーション・サーバ製品でサポートが予定されている。
  3. WindowsだけでなくUNIXサーバでも動作する。

HTML中に直接Javaコードを挿入しておくと、そのHTMLのロード時に自動的かつ一瞬でそれをServlet化し、コンパイルと実行をします。

リクエスト時に jspInit() が呼ばれ、処理終了後 jspDestroy() が呼ばれます。JSPページ中で生成されたオブジェクトは、参照可能な範囲(スコープ)を持ちます。

Fixed Template Data: JSPページ中で直接表記されたHTML部分

Directives: リクエストごとに共有の属性を指定したりする部分

Actions: 処理の詳細を記述する部分

Directives
  <%@ directive ... %>
Actions:
  <xxx xxx="xxx" ... >xxx</xxx>

または

<xxx xxx="xxx" ... >

タグの種類を増やす「Tag extention mechanism」も用意されています。

Scripting elements: declarations/scriptlets/expressions

declarations: パラメータを定義するもの

scriptlets: サブルーチン的に利用されるもの

expressions: リクエストごとに実行されるもの

Javaとの連携が可能なら自由にScripting elementsを定義して実装することもできます。

Bean: Tagインタフェースを実装すると、直接HTMLのコードとの連携が行えます。

Scripting elementsは読みにくく、メンテナンスがしにくいので、多くの場合は単にactionをまとめるための記述に使われる程度でしょう。

XMLに従ってJSPページを記述する方法もあります。

JSPページから生成されるのがHTMLとは限りません。XMLやプレーンテキストも生成可能です。

JPSページ内で発生し、かつcatchされていないThrowableは、ServletRequestオブジェクトの"javax.serlet.jsp.jspException"という名前のattributeとしてputAttribute()されます。

「page isErrorPage=true」というdirectiveで指定されたページにexceptionという変数にそのthrowableを格納して転送することもできます。

通常のHTMLの「Server side include」はJSPに無効なので注意。

ServletとJSPを使い分ける

ServletとJSPを同使い分ければよいのか。その指針を次に示します。

  1. ServletからcallPageメソッドでJSPを呼び出す。HTMLを生成するprintメソッドがなくなるため、Servletプログラマはビジネス・ロジックに専念できる。
  2. ServletプログラマはHTML(出力画面)の作成に必要なデータをJavaオブジェクトにセーブする。
  3. JSPを作成するデザイナーは、JSPの <USERBEAN> タグでJavaオブジェクトへ取り込み、<DISPLAY> タグで属性の値を取り出す。
  4. ServeltとJSPファイルはそれぞれ独立してバージョンアップできる。

利用者からの要求を受け付け、セッションを管理するのはServletである。JSPはServletから呼び出されてHTMLによる出力画面を生成します。

ServletからJSPにデータを渡す手段もあらかじめ用意されています。JSPを呼び出すサーブレットは出力画面を生成するのに必要なデータをJavaオブジェクトに格納した後にcallPageメソッドを使いJSPを呼び出します。

JSPファイルの中では、Javaオブジェクトとを取り込む <USERBEAN> タグ、その属性を取り出して表示する <DISPLAY> タグという専用タグを利用できます。

この枠組みを使うことで、JSP側にはロジックは一切持たせないで開発を進めることができます。

ServletかとJSPを併用するメリットは、ビジネスロジックとプレゼンテーション(画面作成)をきれいに分離できることです。サーブレットの開発者はJavaプログラマである必要がありますが、JSPファイルならばWebデザイナーでも書けるでしょう。ロジックを作るプログラマとプレゼンテーションを作るデザイナーとの分業が可能となります。システム開発の規模が大きくなれば、この分業は効果的になるでしょう。