【最新】JSPとは?概要から簡単な使い方まで紹介


【最新】JSPとは?概要から簡単な使い方まで紹介

1. はじめに:なぜ動的なウェブページが必要なのか?

今日のウェブサイトは、単に静的な情報を表示するだけではありません。ユーザーごとに異なる情報を提供したり、データベースと連携して最新のデータを表示したり、ユーザーからの入力に応じて内容を変えたりと、非常に動的でインタラクティブな体験を提供しています。

しかし、ウェブの基盤であるHTMLは、静的なコンテンツを記述するための言語です。ブラウザがHTMLファイルを受け取ると、そこに書かれた内容をそのまま表示します。ユーザーによって表示内容を変えるためには、サーバー側でリクエストごとに異なるHTMLを生成して返す必要があります。

このような「サーバー側で動的にHTMLを生成する」技術として、様々なものが開発されてきました。その中でもJavaの世界で長年広く使われてきた技術の一つが、JSP(JavaServer Pages) です。

この記事では、JSPがどのような技術なのか、なぜ生まれ、どのように動き、どのように使うのかを、初心者の方にも分かりやすく詳細に解説します。約5000語というボリュームで、JSPの基本から一歩進んだ内容、そして現代における位置づけまでを網羅します。

2. JSPとは? 基本概念の理解

2.1 JSPの定義と目的

JSP(JavaServer Pages) は、サン・マイクロシステムズ(現Oracle)によって開発された、Java技術に基づいたサーバーサイドのスクリプト技術です。その主な目的は、HTML、XML、またはその他のドキュメントタイプの静的なコンテンツの中に、Javaコードを埋め込むことで、動的なウェブページを簡単に作成することにあります。

簡単に言うと、JSPファイルは、見た目はほとんどHTMLですが、その中に特別なタグや構文を使ってJavaのコードを直接記述したり、Javaのオブジェクトを利用したりすることができます。

クライアント(ウェブブラウザ)からJSPファイルへのリクエストがあると、ウェブサーバー(正確にはその上で動作するJSPコンテナやServletコンテナ)がそのリクエストを受け取り、JSPファイルを処理します。この処理によって動的な内容が生成され、最終的に完全なHTMLファイルとしてクライアントに返されます。

2.2 JSPが登場した背景:Servletとの関係性

JSPが登場する以前、Javaで動的なウェブページを生成する主要な技術はServletでした。

Servletは、Javaコードの中にHTMLを文字列として記述し、それをクライアントに返すという仕組みです。例えば、以下のようなコードになります。

java
// 簡単なServletの例(概念コード)
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Hello Servlet</title></head>");
out.println("<body>");
out.println("<h1>Hello from Servlet!</h1>");
// 動的な内容を追加する場合
String name = request.getParameter("name");
if (name != null && !name.isEmpty()) {
out.println("<p>Welcome, " + name + "!</p>");
}
out.println("</body>");
out.println("</html>");
}
}

このServletのコードを見るとわかるように、HTMLタグ一つ一つをout.println()メソッドで出力する必要があります。静的なHTMLの量が少ない場合は問題ありませんが、複雑なレイアウトを持つHTMLを生成しようとすると、Javaコードの中に大量のHTMLタグが文字列として埋め込まれ、非常に読みにくく、保守しにくいコードになってしまいます。HTMLデザイナーとJavaプログラマーの分業も困難でした。

そこで登場したのがJSPです。JSPは、HTMLを主体とし、そこに動的な部分だけをJavaコードで記述するという、Servletとは逆のアプローチをとります。

“`jsp
<%– 簡単なJSPの例 –%>


Hello JSP

Hello from JSP!

<% // Javaコードを埋め込む String name = request.getParameter("name"); if (name != null && !name.isEmpty()) { %>

Welcome, <%= name %>!

<%-- 式で値を出力 --%>
<% } %>

“`

このJSPの例を見ると、HTMLの中にJavaのスクリプトレット(< درصد ... %>)や式(< %= ... %>)が埋め込まれているのが分かります。これにより、HTMLの構造を保ったまま動的な要素を追加できます。

そして、JSPの最も重要な仕組みは、JSPファイルは初回リクエスト時(またはコンテナの起動時)にServletに変換され、コンパイルされてから実行されるという点です。つまり、JSPはServletをより効率的に記述するための「糖衣構文(Syntactic Sugar)」やテンプレートエンジンとして機能するのです。JSPコンテナ(Servletコンテナの一部)がこの変換処理を担当します。

2.3 JSPのメリット

  • 開発効率の向上: HTMLの中に直接Javaコードを記述できるため、ServletのようにHTMLを文字列として扱う必要がなく、見た目を意識しながら開発しやすい。特に、既存の静的なHTMLデザインに動的な要素を少しだけ追加する場合などに便利。
  • プレゼンテーションとロジックの分離支援: Servletが「ビジネスロジックとプレゼンテーションの両方」を扱う傾向があったのに対し、JSPは基本的に「プレゼンテーション層」を担当するという役割分担を促進します。(ただし、JSP内にビジネスロジックを書きすぎると、かえって分離が損なわれるという問題もあります。これについては後述のベストプラクティスで触れます。)
  • HTMLデザイナーとの連携: HTMLの構造がそのまま記述されているため、HTMLデザイナーがデザインを担当し、Javaプログラマーが動的な部分をJSP構文で埋め込むといった分業が比較的容易になる。
  • ホットデプロイ: 変更されたJSPファイルは、サーバーを再起動することなく自動的にリロードされることが多い。(設定によります)

2.4 JSPのデメリット

  • Javaコードの混在: JSP内にJavaスクリプトレットを多用しすぎると、Servletと同様にコードが複雑になり、読みにくく保守が難しくなる。これを「スクリプトレットのスパゲッティ化」と呼ぶこともあります。
  • デバッグの難しさ: JSPファイルはServletに変換されてから実行されるため、JSPファイル上のエラー行と、実際に実行されるServletのコード上のエラー行が一致しないことがあり、デバッグが少し難しくなる場合があります。
  • テストのしにくさ: プレゼンテーション層であるJSPにロジックが混在すると、ユニットテストが困難になります。
  • 最新技術からの遅れ: 近年では、より洗練されたテンプレートエンジン(Thymeleaf, Freemarkerなど)や、クライアントサイドでのレンダリングを行うSPA(Single Page Application)フレームワーク(React, Vue.js, Angularなど)が主流になってきており、新規開発でJSPが第一選択肢となるケースは減ってきています。

デメリットで挙げた「Javaコードの混在」は、JSPの仕組みそのものが持つ性質でもありますが、JSPにはこれを緩和するための機能(JSTLやEL)が用意されており、適切な使い方をすることで、より保守性の高いコードを書くことが可能です。

3. JSPの仕組み:どのように動作するのか?

JSPは、クライアントからのリクエストを受けてからレスポンスを返すまでに、内部でいくつかのステップを踏みます。この仕組みを理解することは、JSPを効果的に利用するために非常に重要です。

3.1 JSPファイルの配置

通常、JSPファイルはWebアプリケーションのルートディレクトリ直下、またはそのサブディレクトリに配置されます。慣習的には、WebContentwebapps/[プロジェクト名]といったディレクトリ内に配置されることが多いです。これらのディレクトリは、ウェブサーバー(Servletコンテナ)から直接アクセス可能な公開領域です。

3.2 初回アクセス時の処理フロー

クライアントが初めて特定のJSPファイルをリクエストした際、JSPコンテナは以下の処理を行います。

  1. リクエストの受信: ウェブサーバーはクライアントからのHTTPリクエストを受け取ります。リクエストURLがJSPファイルを指している場合、そのリクエストはJSPコンテナに渡されます。
  2. JSPファイルの発見: JSPコンテナはリクエストされたパスに対応するJSPファイルを見つけます。
  3. トランスレーション(変換): JSPコンテナは、JSPファイルに記述されたJSP構文(ディレクティブ、スクリプト要素、アクションタグなど)を解析し、対応するJavaコードを持つServletクラスのソースコードに変換します。このServletは、_jspService()のようなメソッドを持ち、このメソッド内でHTML出力やJavaコードの実行が行われます。
    • 例: 先ほどの簡単なJSPコードは、以下のようなServletコードの一部に変換されるイメージです(実際にはもっと複雑です)。
      “`java
      // 生成されるServletコードの一部(概念コード)
      public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
      implements org.apache.jasper.runtime.JspSourceDependent,
      org.apache.jasper.runtime.JspSourceImports {

      // ... 他のメソッドや変数 ...
      
      public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
          throws java.io.IOException, javax.servlet.ServletException {
      
          final javax.servlet.jsp.PageContext pageContext;
          javax.servlet.http.HttpSession session = null;
          final javax.servlet.ServletContext application;
          final javax.servlet.ServletConfig config;
          javax.servlet.jsp.JspWriter out = null;
          final java.lang.Object page = this;
          javax.servlet.jsp.JspWriter _jspx_out = null;
          javax.servlet.jsp.PageContext _jspx_page_context = null;
      
          try {
              response.setContentType("text/html");
              pageContext = _jspxFactory.getPageContext(this, request, response,
                          null, true, 8192, true);
              _jspx_page_context = pageContext;
              application = pageContext.getServletContext();
              config = pageContext.getServletConfig();
              session = pageContext.getSession();
              out = pageContext.getOut();
              _jspx_out = out;
      
              // HTMLの静的な部分を出力
              out.write("<html>\r\n");
              out.write("<head><title>Hello JSP</title></head>\r\n");
              out.write("<body>\r\n");
              out.write("    <h1>Hello from JSP!</h1>\r\n");
              out.write("    ");
              // JSPスクリプトレット内のJavaコード
              String name = request.getParameter("name");
              if (name != null && !name.isEmpty()) {
              out.write("\r\n");
              out.write("            <p>Welcome, ");
              // JSP式で値を出力
              out.print( name );
              out.write("!</p>\r\n");
              out.write("    ");
              }
              out.write("\r\n");
              out.write("</body>\r\n");
              out.write("</html>\r\n");
      
          } catch (java.lang.Throwable t) {
              if (!(t instanceof javax.servlet.jsp.SkipPageException)){
                  out = _jspx_out;
                  if (out != null && out.getBufferSize() != 0)
                      try {
                          if (response.isCommitted()) {
                              out.flush();
                          } else {
                              out.clearBuffer();
                          }
                      } catch (java.io.IOException e) {}
              }
          } finally {
              _jspxFactory.releasePageContext(_jspx_page_context);
          }
      }
      

      }
      ``
      この変換されたServletのソースコードは、通常、サーバーの一時ディレクトリに保存されます。
      4. **コンパイル:** 生成されたServletのソースコードが、標準のJavaコンパイラ(
      javac)によってコンパイルされ、.classファイル(バイトコード)が生成されます。
      5. **ロードとインスタンス生成:** コンパイルされたServletクラスがJVM(Java Virtual Machine)にロードされ、そのクラスのインスタンスが生成されます。
      6. **初期化:** 生成されたServletインスタンスの
      jspInit()メソッド(またはinit()メソッド)が呼び出され、初期化処理が行われます。このメソッドはJSPの宣言(<%! … %>)で記述されたコードが実行される場所でもあります。
      7. **リクエスト処理:** Servletインスタンスの
      _jspService()メソッド(またはservice()メソッド)が呼び出され、実際のリクエスト処理が行われます。このメソッド内で、JSPファイルに記述されたスクリプトレットや式が実行され、HTMLコンテンツが動的に生成されます。
      8. **レスポンスの生成:**
      _jspService()`メソッドは、生成されたHTMLコンテンツを含むHTTPレスポンスを作成します。
      9. レスポンスの送信: 生成されたHTTPレスポンスがクライアント(ブラウザ)に送信されます。ブラウザは受け取ったHTMLを表示します。

3.3 2回目以降のアクセス時の処理

同じJSPファイルに対して2回目以降のリクエストがあった場合、JSPコンテナは上記のような複雑な処理を毎回行う必要はありません。

  • JSPコンテナは、既にそのJSPファイルに対応するServletクラスがメモリ上にロードされ、インスタンス化されていることを確認します。
  • JSPファイルが前回のコンパイル以降に変更されていない場合、トランスレーション、コンパイル、ロード、初期化のステップはスキップされます。
  • 代わりに、既にメモリ上に存在するServletインスタンスの_jspService()メソッドが直接呼び出され、すぐにリクエスト処理とレスポンス生成が行われます。

これにより、2回目以降のアクセスは非常に高速になります。JSPファイルが変更された場合は、変更が検出され、再度トランスレーションとコンパイルが行われます。

3.4 主要な組み込みオブジェクト (Implicit Objects)

JSPコンテナは、JSPファイル内のJavaコード(スクリプト要素やEL式)から、特別な変数名でアクセスできるいくつかのオブジェクトを自動的に生成し、提供します。これらを組み込みオブジェクト (Implicit Objects) と呼びます。これらのオブジェクトはServlet APIに基づいており、ウェブアプリケーション開発において非常に便利です。

主な組み込みオブジェクトは以下の通りです。

オブジェクト名 スコープ 説明
request HttpServletRequest Request クライアントからのリクエストに関する情報(パラメータ、ヘッダーなど)を含む
response HttpServletResponse Page クライアントへ返すレスポンスに関する情報(ヘッダー設定、リダイレクトなど)を含む
out JspWriter Page クライアントへ出力するためのストリーム(HTMLなどを出力する際に使用)
session HttpSession Session クライアントのセッションに関する情報(ユーザー固有の情報保持など)を含む
application ServletContext Application ウェブアプリケーション全体に関する情報(初期パラメータ、ログなど)を含む
config ServletConfig Page このJSPに対応するServletの設定情報を含む
pageContext PageContext Page JSPページのコンテキスト情報。他の組み込みオブジェクトへのアクセスや、属性のスコープ管理に利用
page Object (通常はJSP自身に対応するServletインスタンス) Page このJSPページ自身を参照するオブジェクト(あまり直接使うことはない)
exception Throwable Page エラーページの場合に、発生した例外オブジェクトを含む

これらの組み込みオブジェクトを利用することで、ユーザーからの入力値を取得したり、セッションにユーザー情報を保存したり、アプリケーション全体の設定情報を取得したり、動的にHTMLを出力したりといった処理をJSP内で簡単に行うことができます。

例えば、リクエストパラメータを取得するには request.getParameter("paramName")、セッションに属性を保存するには session.setAttribute("key", value) のように使います。

スコープは、その属性(データ)が保持される有効範囲を示します。
* Pageスコープ: 同じJSPページ内でのみ有効。ページ処理が終了すると破棄されます。
* Requestスコープ: クライアントからの1つのリクエスト内でのみ有効。リクエストの処理が終了すると破棄されます。ServletからJSPにフォワードする場合などにデータの引き渡しに使われます。
* Sessionスコープ: 特定のクライアント(ブラウザ)のセッション期間中有効。ユーザーがサイトを閲覧し続けている間や、ブラウザを閉じるまでなどにデータが保持されます。
* Applicationスコープ: ウェブアプリケーション全体で有効。サーバーが起動している間、すべてのユーザーやリクエストで共有されるデータが保持されます。

4. JSPの構文:基本文法を覚えよう

JSPファイルは主にHTML(またはXMLなど)で構成されますが、動的な部分を記述するために特別な構文要素が用意されています。これらの構文要素は <%%>、または <jsp:> で囲まれるのが特徴です。

4.1 ディレクティブ (Directives)

ディレクティブは、JSPコンテナに対して、JSPファイルの処理方法に関する指示を与える要素です。Servletソースコードへの変換方法などに影響します。通常、JSPファイルの先頭付近に記述されます。

構文は <%@ directive attribute="value" ... %> です。

4.1.1 page ディレクティブ

そのJSPページ全体に関する設定を行います。最も頻繁に使用されるディレクティブです。

例:
jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.Date, java.text.SimpleDateFormat"
errorPage="/error.jsp" isErrorPage="false" %>

主な属性:

  • language: スクリプト言語を指定します。デフォルトはjavaです。
  • contentType: レスポンスのMIMEタイプと文字エンコーディングを指定します。ブラウザにどのような種類のコンテンツであるかを伝えます。通常はtext/html; charset=UTF-8と指定します。
  • pageEncoding: JSPファイル自体の文字エンコーディングを指定します。JSPコンテナがファイルを読み込む際に使用します。contentTypeのcharsetと一致させることが推奨されます。
  • import: JSPページ内で使用するJavaのクラスやパッケージをインポートします。Servletのimport文に相当します。複数のパッケージやクラスをインポートする場合は、カンマで区切ります。java.lang.*, javax.servlet.*, javax.servlet.jsp.*, javax.servlet.http.*は自動的にインポートされます。
  • session: このページでセッションを使用するかどうかを指定します。true(デフォルト)またはfalsefalseにすると、組み込みオブジェクトsessionが利用できなくなります。
  • buffer: 出力バッファのサイズを指定します。デフォルトは8kb。noneを指定するとバッファリングしません。
  • autoFlush: バッファが満杯になったときに自動的にフラッシュするかどうかを指定します。true(デフォルト)またはfalsebuffer="none"の場合はfalseにできません。
  • isThreadSafe: このJSPがスレッドセーフかどうかを指定します。true(デフォルト)またはfalsefalseにすると、リクエストがキューに入れられ、一度に1つのリクエストのみが処理されるようになります(シングルスレッドモデル)。パフォーマンスが低下するため、通常はtrueのままにします。
  • info: このJSPに関する簡単な説明文字列を指定します。
  • errorPage: このページで例外が発生した場合に表示するエラーページのURLを指定します。
  • isErrorPage: このページ自体がエラーページであるかどうかを指定します。trueにすると、組み込みオブジェクトexceptionが利用できるようになります。

4.1.2 include ディレクティブ

他のファイルのコンテンツを、JSPファイルがServletソースコードに変換される際(トランスレーション時)に静的に取り込みます。これは、複数のJSPファイルで共通のヘッダーやフッターなどを利用する場合に便利です。

構文は <%@ include file="relativePath" %> です。

例:
“`jsp
<%@ include file=”header.jspf” %> <%– .jspf はJSP Fragment(断片)を示す慣習的な拡張子 –%>

ページのメインコンテンツ

<%@ include file=”footer.jspf” %>
“`

  • file: 取り込むファイルのパスを、現在のJSPファイルからの相対パスで指定します。
  • 特徴: トランスレーション時に物理的にファイル内容がコピーされるため、インクルードされるファイル内で定義された変数やメソッドは、インクルード元のJSPファイルから参照可能です。ただし、これにより変数名の衝突などが起こる可能性があります。

4.1.3 taglib ディレクティブ

カスタムタグ(JSP Standard Tag Library: JSTL や独自開発のタグなど)を使用可能にするためのディレクティブです。

構文は <%@ taglib uri="tagLibraryURI" prefix="tagPrefix" %> です。

例(JSTL Coreライブラリを使用する場合):
jsp
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

  • uri: タグライブラリを一意に識別するURI(通常はJARファイル内のTLDファイルで定義されています)。
  • prefix: そのタグライブラリのタグを使用する際に、タグ名の前につけるプレフィックスを指定します。例えば、上記の例ではcというプレフィックスを指定しているので、JSTL Coreライブラリのタグは<c:out>, <c:forEach>のように使用します。

4.2 スクリプト要素 (Scripting Elements)

JSPファイル内でJavaコードを記述するための要素です。

4.2.1 スクリプトレット (Scriptlets)

最も基本的なスクリプト要素で、JSPの_jspService()メソッド内に記述される通常のJavaコードブロックです。変数の宣言や代入、条件分岐、ループ処理など、あらゆるJavaの記述が可能です。

構文は <% Java code %> です。

例:
“`jsp
<%
// 変数を宣言し、値を代入
String message = “Hello, JSP!”;
// 条件分岐
if (message != null) {
// 動的な内容を出力(次の「式」要素を使うのが一般的)
out.println(“

” + message + “

“);
}

// リクエストパラメータの取得
String userName = request.getParameter("name");
if (userName != null && !userName.isEmpty()) {
    // セッションへの保存
    session.setAttribute("loggedInUser", userName);
}

%>
“`

注意点: スクリプトレットを多用しすぎると、HTMLとJavaコードが混在して可読性が低下し、保守が難しくなります。これは「スクリプトレットのスパゲッティ化」と呼ばれ、JSPの最も大きな欠点の一つと見なされています。現在では、できる限りスクリプトレットの使用を避け、ELやJSTL、カスタムタグを使用することが推奨されています。

4.2.2 式 (Expressions)

Javaの式の結果を、そのままHTMLとして出力するための要素です。スクリプトレットのようにout.println()を使う必要がなく、より簡潔に値を出力できます。

構文は <%= Java expression %> です。式の末尾にセミコロン(;)は不要です。

例:
“`jsp

現在の時刻:<%= new java.util.Date() %>

ユーザー名:<%= session.getAttribute("loggedInUser") %>

計算結果:<%= 10 + 5 %>

“`

注意点: 式の中に複雑なロジック(条件分岐、ループなど)を書くべきではありません。あくまで「値を評価して出力する」ためのものです。EL(Expression Language)が登場してからは、簡単な値の出力もELで行うことが推奨されるようになり、式の利用頻度は減っています。

4.2.3 宣言 (Declarations)

JSPが変換されるServletクラスの、メソッドやクラス変数などを定義するための要素です。スクリプトレットのように_jspService()メソッド内ではなく、クラスのメンバーとして定義されます。

構文は <%! Java code %> です。

例:
“`jsp
<%!
// クラス変数の宣言
private int hitCounter = 0;

// メソッドの定義
public String getGreeting(String name) {
    if (name == null || name.isEmpty()) {
        return "ゲストさん、こんにちは!";
    } else {
        return name + "さん、ようこそ!";
    }
}

%>
<%
hitCounter++; // スクリプトレット内で宣言した変数を利用
%>

このページは <%= hitCounter %> 回アクセスされました。

<%= getGreeting(request.getParameter("user")) %>

“`

注意点: 宣言で定義されたクラス変数(上記のhitCounterなど)は、そのJSPに対応するServletインスタンス間で共有されます。isThreadSafe="true"(デフォルト)の場合、複数のリクエストが同時に同じServletインスタンスのメソッドを実行するため、スレッドセーフでないクラス変数は競合状態(Race Condition)を引き起こす可能性があります。スレッドセーフにするための適切な同期処理を施すか、そもそも宣言で状態を持つクラス変数を定義しない(RequestスコープやSessionスコープを利用する)ことが推奨されます。

4.3 コメント (Comments)

JSPファイルには、いくつかの種類のコメントを記述できます。

4.3.1 JSPコメント

JSPコンテナによって無視され、生成されるServletコードや最終的なHTML出力には含まれません。JSPのソースコード内にコメントを残す場合に利用します。

構文は <%-- comment text --%> です。

例:
jsp
<%-- これはJSPコメントです。ブラウザのソース表示では見えません。 --%>

4.3.2 HTMLコメント

JSPコンテナによって通常のテキストとして扱われ、生成されるHTML出力に含まれます。ブラウザでページのソースを表示すると確認できます。

構文は <!-- comment text --> です。

例:
“`jsp

“`

4.3.3 Javaコメント

スクリプト要素(スクリプトレット、宣言)の中に記述されたJavaコード内のコメントです。生成されるServletコードのJavaコメントとして含まれますが、最終的なHTML出力には含まれません。

構文は // single-line comment または /* multi-line comment */ です。

例:
jsp
<%
// 変数を初期化
int count = 0;
/*
* カウントアップ処理
* count++;
*/
%>

4.4 アクションタグ (Action Elements)

アクションタグは、JSPコンテナに特定のアクション(別のページへのリクエスト転送やインクルード、JavaBeansの操作など)を実行させるためのXML構文に基づいた要素です。

構文は <jsp:actionName attribute="value" ... > または <jsp:actionName attribute="value" ... /> です。

4.4.1 <jsp:include>

他のリソース(JSP、HTML、Servletなど)をリクエスト時に動的にインクルードします。インクルードされるリソースは独立して実行され、その出力結果が現在のJSPの出力に組み込まれます。

構文は <jsp:include page="relativePath" flush="true|false" /> です。

例:
“`jsp
<%– menu.jspの内容をここに動的に含める –%>

メインコンテンツ

<%– HTMLファイルも可 –%>
“`

  • page: インクルードするリソースのパスを指定します。アプリケーションルートからの絶対パス(/...)または現在のJSPからの相対パスで指定できます。
  • flush: 出力バッファをフラッシュするかどうかを指定します。デフォルトはfalse

<%@ include %> ディレクティブとの違い:

機能 <%@ include file="..." %> <jsp:include page="..." />
処理タイミング トランスレーション時 (静的) リクエスト時 (動的)
仕組み ファイル内容をコピーして1つのServletに インクルードされるリソースを独立したリクエストとして実行し、出力を取り込む
変数/スコープ インクルード元と共有 インクルードされるリソースは新しいPageスコープを持つ(Requestスコープなどは共有)
パフォーマンス 高速 わずかにオーバーヘッドがある
用途 共通のコード断片 (ヘッダー、フッター、関数定義など) 独立したコンポーネント(メニュー、フッター、広告ブロックなど)

4.4.2 <jsp:forward>

リクエストの処理を別のリソース(JSP、HTML、Servletなど)に転送します。現在のJSPの以降の処理は破棄され、転送先のレスポンスがクライアントに返されます。ブラウザのURLは転送前のまま変わらないのが特徴です。

構文は <jsp:forward page="relativePath" /> です。

例:
“`jsp
<%
// ログインしているかチェック
if (session.getAttribute(“loggedInUser”) == null) {
%>
<%– 未ログインならログインページへ転送 –%>
<%
}
%>
<%– ログイン済みの場合のみ表示される内容 –%>

会員ページ

“`

  • page: 転送先のリソースのパスを指定します。

4.4.3 <jsp:param>

<jsp:include><jsp:forward> のタグの中に記述することで、転送先やインクルード先にパラメータを渡すことができます。

構文は <jsp:param name="paramName" value="paramValue" /> です。

例:
“`jsp

<%– content.jspにarticleIdパラメータを渡す –%>


<%– SearchServletにqueryパラメータを渡す –%>

“`

転送先・インクルード先では、組み込みオブジェクトrequestを使ってパラメータを取得できます。

“`jsp
<%– content.jsp または /search Servlet 内で –%>

記事ID: <%= request.getParameter("articleId") %>

カテゴリ: <%= request.getParameter("category") %>

検索クエリ: <%= request.getParameter("query") %>

“`

4.4.4 <jsp:useBean>

JavaBeansをページ内で利用可能にするためのアクションタグです。指定したスコープ内に、指定したクラスのインスタンスが存在しない場合は新しく生成し、存在する場合はそのインスタンスを参照します。

構文は <jsp:useBean id="beanName" class="package.ClassName" scope="page|request|session|application" /> です。

例:
“`jsp
<%– package.UserBean クラスのインスタンスをセッションスコープで取得/生成し、userという名前で参照 –%>

ユーザー名(ビーンから取得):<%= user.getUserName() %>

<%– スクリプトレットや式で利用 –%>
“`

  • id: JavaBeansを参照するための変数名を指定します。
  • class: 使用するJavaBeansの完全限定クラス名を指定します。
  • scope: JavaBeansをどのスコープで管理するかを指定します(page, request, session, application)。デフォルトはpage

4.4.5 <jsp:setProperty> および <jsp:getProperty>

<jsp:useBean>で取得または生成したJavaBeansのプロパティを設定または取得するためのアクションタグです。

構文:
* プロパティの設定: <jsp:setProperty name="beanName" property="propertyName" value="propertyValue" />
* プロパティの設定(リクエストパラメータから自動設定): <jsp:setProperty name="beanName" property="propertyName" param="requestParamName" />
* 全プロパティの設定(リクエストパラメータから自動設定): <jsp:setProperty name="beanName" property="*" />
* プロパティの取得: <jsp:getProperty name="beanName" property="propertyName" />

例:
“`jsp

<%– フォームからの入力(リクエストパラメータ)をUserBeanのプロパティに自動設定 –%>

<%– または個別に設定 –%>
<%– –%>
<%– –%>

登録されたユーザー情報:

名前:

<%– プロパティの取得 –%>

年齢:

“`

これらのアクションタグは、JavaBeansを使ったM odel 1アーキテクチャ(JSPがリクエスト処理とビュー表示の両方を行う)において、フォーム入力値とBeanの連携を簡潔に記述するために設計されました。

4.5 Expression Language (EL)

JSP 2.0で導入されたELは、JSPページからJavaBeansのプロパティやコレクションの要素、組み込みオブジェクトの属性などに簡単にアクセスするための言語です。JavaコードをJSPから追い出し、プレゼンテーション層をよりシンプルに保つことを目的としています。

構文は ${ expression } です。

例:
“`jsp
<%– スクリプトレットや式の代わりにELを使う例 –%>

<%– requestスコープに”message”という名前で属性が格納されていると仮定 –%>

${ requestScope.message }

<%– Requestスコープのmessage属性を取得 –%>

${ message }

<%– スコープを指定しない場合は、Page, Request, Session, Applicationの順で探索 –%>

<%– sessionスコープに”loggedInUser”というUserBeanのインスタンスが格納されていると仮定 –%>

ユーザー名: ${ sessionScope.loggedInUser.userName }

<%– Beanのプロパティにアクセス –%>

年齢: ${ loggedInUser.age }

<%– リクエストパラメータ”name”を取得 –%>

パラメータ name の値: ${ param.name }

<%– HTTPヘッダー”User-Agent”を取得 –%>

User Agent: ${ header[‘User-Agent’] }

<%– 特殊文字を含む場合は [] を使う –%>

<%– リストや配列の要素にアクセス –%>
<%– requestScope.userList というListにUserBeanのリストが格納されていると仮定 –%>

  • ${ user.userName } (${ user.age }歳)

“`

ELは、組み込みオブジェクトやその属性、JavaBeansのプロパティへのアクセス、配列やリストの要素へのアクセス、基本的な算術演算子、論理演算子、比較演算子、条件演算子などをサポートしています。また、JSTLと組み合わせて使うことで、ループや条件分岐もEL式を使って簡潔に記述できます。

ELを使うことで、スクリプトレットや<jsp:getProperty>などを排除し、JSPの可読性と保守性を大幅に向上させることができます。現代のJSP開発では、ELとJSTLを使うのが標準的なスタイルです。

4.6 JSTL (JSP Standard Tag Library)

JSTLは、JSP開発を支援するために標準化されたカスタムタグのセットです。データの繰り返し処理、条件分岐、XML処理、国際化、SQLデータベースアクセスなどの一般的なタスクを、JSPページ内にJavaコードを書くことなく実行できるようにします。

JSTLはいくつかのタグライブラリに分かれています。主に使われるのは以下のものです。

  • Core (cプレフィックス): 条件分岐 (<c:if>, <c:choose>, <c:when>, <c:otherwise>), 繰り返し (<c:forEach>, <c:forTokens>), 変数操作 (<c:set>, <c:remove>, <c:catch>), URL操作 (<c:url>, <c:redirect>, <c:param>), 出力 (<c:out>) など。
  • Formatting (fmtプレフィックス): 日付/時刻、数値、通貨の書式設定、国際化 (<fmt:message>, <fmt:formatDate>, <fmt:formatNumber>) など。
  • SQL (sqlプレフィックス): データベース操作 (<sql:query>, <sql:update>)。ただし、ビュー層であるJSPに直接DBアクセス処理を書くのはMVCの原則に反するため、あまり推奨されません。
  • XML (xプレフィックス): XML処理 (<x:parse>, <x:forEach>, <x:if>, <x:out>)。
  • Functions (fnプレフィックス): 文字列操作やコレクション操作のためのEL関数 (fn:length, fn:substring, fn:contains) など。

JSTLを使用するには、まずJSTLライブラリ(JARファイル)をWebアプリケーションのWEB-INF/libディレクトリに配置し、JSPファイルの先頭でtaglibディレクティブを使ってインポートします。

例:
“`jsp
<%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
<%@ taglib uri=”http://java.sun.com/jsp/jstl/fmt” prefix=”fmt” %>

<%– RequestスコープにitemsというListが格納されていると仮定 –%>
<%– ELと組み合わせて条件分岐 –%>

    <%– リストの繰り返し処理 –%>

  • <%– 値の出力(エスケープ処理も可能) –%>
    () <%– 数値の書式設定 –%>


商品はありません。

<%– 現在の日付と時刻を表示 –%>

<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<display-name>My Web Application</display-name>
<description>
A simple JSP example.
</description>
<!-- 必要に応じてServletマッピングなどをここに追加 -->
</web-app>
(注: TomcatのバージョンによってはJakarta EEのバージョンが異なります。適宜読み替えてください。)

これで、Tomcat上でJSPを実行するための基本的な準備が整いました。

5.2 簡単なJSPファイルの作成と実行

アプリケーションディレクトリ (mywebapp) の直下(またはサブディレクトリ)にJSPファイルを作成します。

hello.jsp
“`jsp
<%@ page language=”java” contentType=”text/html; charset=UTF-8″
pageEncoding=”UTF-8″%>





Hello JSP Page

初めてのJSPページ

これは静的なHTMLです。

<%-- スクリプトレットでJavaコードを記述 --%>
<% java.util.Date now = new java.util.Date(); java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy年MM月dd日 HH時mm分ss秒"); String formattedDate = sdf.format(now); %>

<%-- 式で変数を出力 --%>

現在の時刻は <%= formattedDate %> です。

<%-- 組み込みオブジェクト request を利用してパラメータを取得 --%>
<% String name = request.getParameter("name"); %>
<%-- ELでパラメータを取得し、条件分岐(JSTLが必要ですが、ここではJavaで) --%>
<% if (name != null && !name.isEmpty()) { %>

こんにちは、<%= name %> さん!

<% } else { %>

名前が指定されていません。

<% } %>

<%-- ELのみでパラメータを取得(JSTL Coreライブラリが必要) --%>
<%-- JSTLとELを使う場合: --%>
<%-- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> –%>
<%-- –%>
<%--

こんにちは、${ param.name } さん! (EL)

–%>
<%-- –%>
<%-- –%>
<%--

名前が指定されていません。(EL)

–%>
<%-- –%>


“`

  1. 上記のコードを mywebapp/hello.jsp として保存します。
  2. Tomcatのインストールディレクトリにあるbinディレクトリを開き、コマンドプロンプトやターミナルでcatalina.bat run (Windows) またはcatalina.sh run (Linux/macOS) を実行してTomcatを起動します。
  3. ウェブブラウザを開き、http://localhost:8080/mywebapp/hello.jsp にアクセスします。(8080はTomcatのデフォルトポート。異なる場合は適宜変更)

ブラウザに以下のような内容が表示されるはずです。

初めてのJSPページ
これは静的なHTMLです。
現在の時刻は [現在の日時] です。
名前が指定されていません。

次に、パラメータ付きでアクセスしてみましょう。

http://localhost:8080/mywebapp/hello.jsp?name=Taro

今度は以下のように表示が変わるはずです。

初めてのJSPページ
これは静的なHTMLです。
現在の時刻は [現在の日時] です。
こんにちは、Taro さん!

これで、JSPファイルがサーバーサイドで処理され、動的な内容を含むHTMLが生成されてブラウザに表示されることを確認できました。

5.3 サーブレットと連携するJSP (MVCの導入)

実際のウェブアプリケーション開発では、ビジネスロジックやデータ処理はServlet(または他のJavaクラス)で行い、JSPはデータの表示のみを担当するという役割分担(Model-View-Controller: MVCパターン)が一般的です。

ここでは、Servletで簡単なデータを作成し、それをJSPに渡して表示する例を示します。

  1. Servletクラスの作成:
    アプリケーションディレクトリ (mywebapp) の中に、Servletクラスを配置するためのディレクトリ構造を作成します。例えば、WEB-INF/classes/com/example/servlet/ とします。
    ここに以下のJavaファイルを作成します。

    WEB-INF/classes/com/example/servlet/DataControllerServlet.java
    “`java
    package com.example.servlet;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;

    import jakarta.servlet.RequestDispatcher;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;

    // @WebServletアノテーションでURLマッピングを指定 (Servlet 3.0以降)
    @WebServlet(“/data”)
    public class DataControllerServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1. データ(Model)を作成する
        List<String> itemList = new ArrayList<>();
        itemList.add("アイテムA");
        itemList.add("アイテムB");
        itemList.add("アイテムC");
    
        // 2. データをRequestスコープに格納する
        request.setAttribute("items", itemList);
    
        // 3. 表示を担当するJSP(View)に処理をフォワードする
        RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/displayData.jsp");
        dispatcher.forward(request, response);
    }
    

    }
    ``
    このServletをコンパイルし、生成された
    .classファイルをWEB-INF/classes/com/example/servlet/` ディレクトリに配置します。(IDEを使っている場合は自動的に行われます)

  2. JSPファイル (View) の作成:
    表示を担当するJSPファイルを、クライアントから直接アクセスできないWEB-INFディレクトリの中に作成します。慣習としてWEB-INF/jsp/のようなサブディレクトリにまとめることが多いです。

    WEB-INF/jsp/displayData.jsp
    “`jsp
    <%@ page language=”java” contentType=”text/html; charset=UTF-8″
    pageEncoding=”UTF-8″%>
    <%– JSTL Coreライブラリを使用 –%>
    <%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
    <!DOCTYPE html>



    データ表示ページ

    Servletから渡されたデータ

    <%-- Servletから渡されたリスト(Requestスコープの"items")をJSTLのforEachタグとELで表示 --%>
    <c:if test="${ not empty requestScope.items }">
        <ul>
            <c:forEach var="item" items="${ requestScope.items }">
                <li><c:out value="${ item }" /></li>
            </c:forEach>
        </ul>
    </c:if>
    <c:if test="${ empty requestScope.items }">
        <p>表示するデータがありません。</p>
    </c:if>
    
    <p><a href="<%= request.getContextPath() %>/data">もう一度読み込む</a></p>
    



    ``
    JSTLを使用しているため、**JSTLライブラリ(
    jstl-api.jarjstl-impl.jar)をダウンロードし、mywebapp/WEB-INF/lib/ディレクトリに配置する**必要があります。(Jakarta EE 9以降の場合はjakarta.servlet.jsp.jstl-api.jarjakarta.servlet.jsp.jstl.impl.jar`など)

  3. 実行:
    Tomcatを再起動し、ブラウザで http://localhost:8080/mywebapp/data にアクセスします。

Tomcatは /mywebapp/data へのリクエストを DataControllerServlet にマッピングします(@WebServletアノテーションまたはweb.xmlの設定による)。Servletはデータを作成し、Requestスコープに格納した後、/WEB-INF/jsp/displayData.jsp にフォワードします。JSPはRequestスコープからデータを取得し、JSTLのforEachタグを使ってリストの内容を動的に表示します。最終的に生成されたHTMLがブラウザに表示されます。

この例は、Controller(Servlet)がModel(データ)を準備し、View(JSP)にそれを表示させるという、MVCの基本的な考え方を示しています。JSPファイル自体にはビジネスロジックはほとんどなく、データの表示に特化しています。

5.4 フォーム入力とJSP

ユーザーからのフォーム入力を受け取り、JSPで処理して表示する基本的な例です。

  1. 入力フォーム用JSPの作成:

    mywebapp/inputForm.jsp
    jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>入力フォーム</title>
    </head>
    <body>
    <h1>名前を入力してください</h1>
    <%-- フォームの送信先を processForm.jsp に指定 --%>
    <form action="processForm.jsp" method="post">
    <label for="userName">名前:</label>
    <input type="text" id="userName" name="userName">
    <br><br>
    <input type="submit" value="送信">
    </form>
    </body>
    </html>

  2. フォーム処理用JSPの作成:

    mywebapp/processForm.jsp
    “`jsp
    <%@ page language=”java” contentType=”text/html; charset=UTF-8″
    pageEncoding=”UTF-8″%>
    <%– JSTL Coreライブラリを使用 –%>
    <%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
    <!DOCTYPE html>



    入力結果

    入力結果

    <%-- リクエストパラメータから"userName"の値を取得 --%>
    <%
        String name = request.getParameter("userName");
    %>
    
    <%-- 取得した値を表示(Javaコード) --%>
    <% if (name != null && !name.trim().isEmpty()) { %>
        <p>入力された名前: <%= name %></p>
    <% } else { %>
        <p>名前が入力されていません。</p>
    <% } %>
    
    <hr>
    
    <%-- 取得した値をELで表示(JSTL/EL利用) --%>
    <c:if test="${ not empty param.userName }">
         <p>入力された名前 (EL): <c:out value="${ param.userName }" /></p>
    </c:if>
    <c:if test="${ empty param.userName }">
         <p>名前が入力されていません。(EL)</p>
    </c:if>
    
    <p><a href="inputForm.jsp">フォームに戻る</a></p>
    



    “`

  3. 実行:
    Tomcatが起動していることを確認し、ブラウザで http://localhost:8080/mywebapp/inputForm.jsp にアクセスします。
    フォームに名前を入力して送信すると、processForm.jsp に遷移し、入力した名前が表示されます。

この例では、リクエストパラメータをJSP内で直接 request.getParameter() や EL (${ param.userName }) で取得しています。実際のアプリケーションでは、フォームの送信先をServletにし、Servletで入力値のバリデーションやビジネスロジックを実行してから、結果表示用のJSPにフォワードするという構成が推奨されます。

5.5 セッション管理

JSPでは、組み込みオブジェクトsessionを使ってセッション情報を簡単に管理できます。

例:ログイン後のユーザー名をセッションに保存し、別のページで表示する

  1. ログイン処理用JSP(簡略版)の作成:

    mywebapp/loginProcess.jsp
    “`jsp
    <%@ page language=”java” contentType=”text/html; charset=UTF-8″
    pageEncoding=”UTF-8″%>
    <%
    // フォームから送信された名前(userName)を取得
    String userName = request.getParameter(“userName”);

    if (userName != null && !userName.trim().isEmpty()) {
        // 取得した名前をセッションに保存
        session.setAttribute("loggedInUser", userName);
        // ログイン成功後のページにリダイレクト
        response.sendRedirect("welcome.jsp");
    } else {
        // 名前が未入力の場合はエラーメッセージを表示してフォームに戻るなど
        // ここでは単純にフォームに戻ります
        response.sendRedirect("inputForm.jsp");
    }
    

    %>
    “`

  2. ログイン成功後ページ用JSPの作成:

    mywebapp/welcome.jsp
    “`jsp
    <%@ page language=”java” contentType=”text/html; charset=UTF-8″
    pageEncoding=”UTF-8″%>
    <%@ taglib uri=”http://java.sun.com/jsp/jstl/core” prefix=”c” %>
    <!DOCTYPE html>



    ようこそページ

    ようこそ!

    <%-- セッションから保存したユーザー名を取得 --%>
    <% String user = (String)session.getAttribute("loggedInUser"); %>
    
    <%-- 取得したユーザー名を表示(Javaコード) --%>
    <% if (user != null) { %>
        <p><%= user %> さん、ログイン成功です!</p>
    <% } else { %>
        <p>ユーザー情報がありません。</p>
    <% } %>
    
    <hr>
    
    <%-- 取得したユーザー名をELで表示(JSTL/EL利用) --%>
    <c:if test="${ not empty sessionScope.loggedInUser }">
        <p>${ sessionScope.loggedInUser } さん、ログイン成功です! (EL)</p>
    </c:if>
    <c:if test="${ empty sessionScope.loggedInUser }">
        <p>ユーザー情報がありません。(EL)</p>
    </c:if>
    
    <p><a href="logout.jsp">ログアウト</a></p>
    



    “`

  3. ログアウト処理用JSPの作成:

    mywebapp/logout.jsp
    jsp
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <%
    // セッションを無効化(破棄)する
    session.invalidate();
    // ログアウト後のページにリダイレクト
    response.sendRedirect("inputForm.jsp");
    %>

  4. inputForm.jsp のフォーム送信先を loginProcess.jsp に変更:
    inputForm.jspform タグの action 属性を "loginProcess.jsp" に変更します。
    html
    <form action="loginProcess.jsp" method="post">
    <label for="userName">名前:</label>
    <input type="text" id="userName" name="userName">
    <br><br>
    <input type="submit" value="送信">
    </form>

  5. 実行:
    Tomcatが起動していることを確認し、ブラウザで http://localhost:8080/mywebapp/inputForm.jsp にアクセスします。
    名前を入力して送信すると loginProcess.jsp が実行され、セッションに名前が保存された後 welcome.jsp にリダイレクトされます。welcome.jsp ではセッションから名前を取得して表示します。「ログアウト」リンクをクリックすると logout.jsp が実行され、セッションが破棄された後 inputForm.jsp にリダイレクトされます。

この例では、セッションにログイン状態を保持し、異なるJSPページ間でその情報を共有できることを示しています。セッション管理は、ショッピングカート、ユーザー認証、パーソナライズなどの機能で不可欠です。

6. JSP開発におけるベストプラクティスと注意点

JSPは強力な技術ですが、その柔軟性ゆえに不適切な使い方をすると保守性の低いコードを生み出す可能性があります。より良いJSPアプリケーションを開発するためのベストプラクティスをいくつか紹介します。

6.1 MVCモデルの適用

前述したように、JSP開発において最も重要な原則の一つは、Model-View-Controller (MVC) パターンを適用することです。

  • Model: アプリケーションが扱うデータやビジネスロジック(データベースアクセス、計算、バリデーションなど)。
  • View: ユーザーインターフェース(HTMLの表示)。JSPがこの役割を担います。
  • Controller: ユーザーからのリクエストを受け付け、どのModelを使用し、どのViewを表示するかを決定するロジック。通常、Servletがこの役割を担います。

MVCに基づいた開発では、以下のような役割分担が推奨されます。

  1. クライアントからのリクエストをServlet(Controller)が受け取る。
  2. Servletは、リクエストの内容に応じてModel(ビジネスロジックを実装したJavaクラス)を呼び出し、必要なデータを取得したり処理を実行したりする。
  3. Modelから取得したデータをServletがRequestスコープやSessionスコープなどに格納する。
  4. Servletは、表示すべきJSP(View)を決定し、RequestDispatcherを使ってそのJSPにフォワードする。
  5. JSPは、スコープに格納されたデータを取り出し、それを使って動的なHTMLを生成する。JSPにはデータの表示に関するロジックのみを記述し、データ取得や複雑な計算などのビジネスロジックは書かない。

このように役割を分担することで、以下のようなメリットが得られます。

  • 関心の分離 (Separation of Concerns): ビジネスロジックとプレゼンテーションロジックが明確に分離されるため、コードの見通しが良くなり、保守や改修が容易になります。
  • 再利用性: ModelやControllerのロジックは、JSPだけでなく、Webサービスや他のクライアントからも再利用可能になります。JSPファイルも、異なるControllerから同じデータを使って表示される可能性があります。
  • テスト容易性: ビジネスロジック(Model)やControllerのロジックを、JSPから分離して単体テストしやすくなります。
  • 開発効率: UIデザイナーはJSP(HTML)に集中でき、JavaプログラマーはServletやビジネスロジックに集中するといった分業が進めやすくなります。

避けるべきこと: J SPファイル内に大量のJavaスクリプトレットを記述して、データ取得からビジネスロジック、表示ロジックまですべてを一つのJSPファイルで行う、いわゆるModel 1アーキテクチャ的な書き方は、小規模なサンプル以外では避けるべきです。

6.2 スクリプトレットの多用を避ける (EL, JSTL, カスタムタグの活用)

MVCの原則とも関連しますが、JSPファイル内でJavaスクリプトレット(< درصد ... %>)や式(< %= ... %>)を多用することは避けるべきです。これらはHTMLの中にJavaコードが混ざり合い、可読性の低下や保守の困難さを招きます。

代わりに、以下の技術を活用することを強く推奨します。

  • Expression Language (EL): データの取得や簡単な表示にはEL (${ ... }) を使用します。これにより、< %= request.getParameter("name") %> と書く代わりに ${ param.name } と書けるなど、記述が非常に簡潔になります。JavaBeansのプロパティへのアクセスも ${ user.userName } のように直感的に書けます。
  • JSP Standard Tag Library (JSTL): 条件分岐 (<c:if>, <c:choose>) や繰り返し処理 (<c:forEach>)、変数の設定 (<c:set>)、出力 (<c:out>) など、表示に関する共通的なロジックにはJSTLを使用します。これにより、JSP内にJavaのif文やforループを書く必要がなくなります。
  • カスタムタグ: 独自の複雑な表示ロジックや、特定の機能をカプセル化したい場合は、カスタムタグを開発して利用します。これにより、JSPファイルはよりクリーンなHTMLに近い記述になります。

JSTLとELを組み合わせることで、JSPファイルはほぼHTMLとタグライブラリのタグで構成され、Javaコードの記述を最小限に抑えることができます。これが、現代のJSP開発における標準的なスタイルです。

6.3 エラーハンドリング

ウェブアプリケーションにおいて、エラー発生時の適切な対応はユーザーエクスペリエンスとセキュリティの観点から重要です。JSPでは、pageディレクティブのerrorPage属性とisErrorPage属性を使って、ページレベルのエラーハンドリングを設定できます。

  • エラーが発生する可能性のあるJSPファイルに <%@ page errorPage="/path/to/errorpage.jsp" %> と記述しておくと、そのページで捕捉されない例外が発生した場合に、指定したエラーページにリクエストがフォワードされます。
  • エラーページとして機能するJSPファイルには <%@ page isErrorPage="true" %> と記述します。これにより、組み込みオブジェクトexceptionが利用可能になり、発生した例外の情報 (exception.getMessage(), exception.printStackTrace()など) を表示したり、ログに記録したりすることができます。

アプリケーション全体のエラーハンドリングは、web.xml<error-page>要素を記述して、特定の例外タイプやHTTPステータスコードに対応するエラーページを設定するのが一般的です。

“`xml


java.lang.Throwable <%– すべての例外を捕捉 –%>
/WEB-INF/jsp/error/error500.jsp


404 <%– 404 Not Found エラー –%>
/WEB-INF/jsp/error/error404.jsp

“`

6.4 デバッグ方法

JSPはServletに変換されて実行されるため、Javaのデバッグ手法が適用可能です。

  • 標準出力/ログ: JSP内で System.out.println()application.log() (組み込みオブジェクトapplicationを利用) を使うことで、Tomcatのコンソールやログファイルに情報を出力できます。
  • IDEのデバッガー: EclipseやIntelliJ IDEAなどのIDEを使用している場合、JSPファイルにブレークポイントを設定できます。IDEはJSPファイルと生成されたServletコード間のマッピングを知っており、JSPファイル上のブレークポイントで実行を一時停止させ、変数の値などを調べることが可能です。ただし、JSPコンテナによってはデバッグ情報の生成設定が必要な場合があります。
  • 例外スタックトレース: エラー発生時には、通常、サーバーコンソールやブラウザにスタックトレースが表示されます。これにより、エラーが発生したServletクラスとそのコード上の行番号が特定できます。JSPコンテナによっては、生成されたServletコードと元のJSPコードの対応関係を示すコメントなどが付加されており、デバッグの手助けになります。

6.5 セキュリティに関する考慮事項

JSPで動的なコンテンツを生成する際には、いくつかのセキュリティリスクに注意が必要です。

  • XSS (Cross-Site Scripting) 対策: ユーザーからの入力値やデータベースから取得した値をそのままHTMLとして出力すると、悪意のあるスクリプトが埋め込まれる可能性があります。これを防ぐためには、出力する値に対してHTMLエスケープ処理を行う必要があります。JSTLの<c:out>タグはデフォルトでエスケープ処理を行うため安全です(escapeXml="true"属性)。スクリプトレットで出力する場合は、Apache Commons Textなどのライブラリを使って明示的にエスケープ処理を行います。
    “`jsp
    <%– 安全な出力 (JSTL + EL) –%>

    入力値:

    <%– 危険な出力 (スクリプトレット、エスケープなし) –%>
    <%–

    入力値: <%= request.getParameter(“userInput”) %>

    –%>

    <%– 安全な出力 (スクリプトレット、エスケープあり) –%>
    <%– <%
    String userInput = request.getParameter(“userInput”);
    if (userInput != null) {
    out.println(“

    入力値: ” + org.apache.commons.text.StringEscapeUtils.escapeHtml4(userInput) + “

    “);
    }
    %> –%>
    ``
    * **SQLインジェクション対策:** JSPのスクリプトレット内で直接データベースアクセスを行い、ユーザー入力値をSQLクエリに埋め込むのは非常に危険です。SQLインジェクションを防ぐためには、**プリペアドステートメント**を使用することが不可欠です。DBアクセスはビュー層であるJSPではなく、Model層のJavaクラスで行うべきです。JSTLの
    タグもプリペアドステートメントをサポートしていますが、前述の通りJSPでDBアクセス自体を推奨しません。
    * **ファイルの配置:** クライアントから直接アクセスされるべきではないファイル(設定ファイル、Javaクラスファイル、Controllerの役割を担うJSPなど)は、
    WEB-INFディレクトリ以下に配置します。JSPファイルでも、Servletからフォワードされるだけで直接URLでアクセスされることを想定していないものはWEB-INF/jsp/`などのサブディレクトリに置くのが良いでしょう。

7. JSPの現在と将来

JSPは古くから存在する技術であり、現代のウェブ開発の風景は大きく変化しました。JSPは現在どのような位置づけにあり、将来はどうなっていくのでしょうか。

7.1 JSPの普及状況

JSPは、特に2000年代から2010年代にかけて、Javaベースのエンタープライズアプリケーション開発において非常に広く使われました。多くの既存システムやフレームワーク(Struts, Spring MVCの初期など)で採用されており、現在でもこれらのシステムを保守・運用するためにJSPのスキルは依然として必要とされています。

また、学習コストが比較的低いことや、HTMLの知識があれば入りやすいことから、簡単なウェブアプリケーションや学習目的でJSPが使われることもあります。

7.2 代替技術

近年、JSPに代わる(あるいはJSPよりも推奨される)プレゼンテーション層技術が数多く登場しています。

  • 他のサーバーサイドテンプレートエンジン:

    • Thymeleaf: Javaで最も人気の高いテンプレートエンジンの一つです。HTMLファイルに直接記述でき、HTMLとして妥当な構文(Natural Templates)を持つため、静的なプロトタイプと動的なテンプレートを兼ねることができます。Spring Frameworkとの連携が強力です。
    • FreeMarker: 別の強力なテンプレートエンジンで、Javaだけでなく他の言語からも利用可能です。独自のテンプレート言語を持ちます。
    • Velocity: シンプルで高速なテンプレートエンジンです。

    これらのテンプレートエンジンは、JSPのスクリプトレット問題を解決し、プレゼンテーションとロジックの分離をより徹底しやすい構造になっています。

  • クライアントサイドレンダリング (SPAフレームワーク):

    • React, Vue.js, Angular: これらのJavaScriptフレームワークは、ブラウザ側で大部分のHTMLを動的に生成・操作します。サーバーはデータ(通常はJSON形式)をAPIとして提供し、クライアントサイドのJavaScriptがそのデータを受け取ってHTMLを構築・更新します。これにより、サーバーサイドでのHTML生成の必要性が減り、ユーザーインターフェースの応答性が向上します。

    SPAフレームワークの登場により、従来のサーバーサイドレンダリング技術(JSPを含む)は、管理画面やSEOが特に重要なサイト、初回表示速度を重視するサイトなど、特定の用途で使われることが多くなっています。

7.3 現代のウェブ開発におけるJSPの位置づけ

新しいJavaベースのウェブアプリケーションをゼロから開発する場合、多くの場合、JSPよりもThymeleafのようなテンプレートエンジンや、Spring Bootと組み合わせたRESTful API + SPAといったアーキテクチャが選択される傾向にあります。

しかし、JSPが完全に不要になったわけではありません。

  • 既存システムの保守: 多くのレガシーシステムがJSPで構築されているため、これらのシステムを維持・改修するためにはJSPの知識が不可欠です。
  • 一部のフレームワークでのサポート: Spring Bootのようなモダンなフレームワークでも、JSPをビュー技術として使用することが可能です(ただし、Thymeleafなどが推奨されることが多いです)。小規模なアプリケーションや、既存のJSP資産を活用したい場合に選択肢となり得ます。
  • シンプルなユースケース: ごく単純な動的ページであれば、JSPが手軽な選択肢となる場合もあります。

JSPはJava EE (Jakarta EE) 標準の一部であり、Servletコンテナが動作する環境であれば基本的に使用可能です。これは大きな強みです。しかし、他のモダンな技術と比較すると、特にプレゼンテーションロジックの記述方法や、大規模・複雑なアプリケーションにおける保守性の面で課題があるため、新規開発での優先順位は下がっていると言えます。

「最新」という観点から見ると、JSPそのものに大きな機能追加や変更は近年ほとんどありません。最新のJavaバージョンやServletコンテナ上でJSPを動作させる場合の互換性や設定方法が「最新の考慮事項」となります。また、JSTLやELといった関連技術を使いこなすことが、現代的なJSP開発スタイルとなります。

8. まとめ:JSPを理解する意義

この記事では、JSP(JavaServer Pages)について、その定義、Servletとの関係性、内部の仕組み、基本的な構文(ディレクティブ、スクリプト要素、アクションタグ)、そして現代の開発に不可欠なELとJSTLについて詳細に解説しました。また、簡単なサンプルを通じて具体的な使い方を示し、JSP開発におけるベストプラクティスや現在のウェブ開発における位置づけについても触れました。

JSPは、静的なHTMLに動的なJavaコードを埋め込むことで、サーバーサイドでの動的なウェブページ生成を可能にする技術です。その最も重要な特徴は、JSPファイルが初回リクエスト時にServletに変換されて実行されるという仕組みです。

かつてはJavaウェブ開発の主要なプレゼンテーション技術でしたが、スクリプトレットの多用によるコードの混在や保守性の問題から、JSTLやELといった関連技術の進化、そしてThymeleafのような代替テンプレートエンジンやSPAフレームワークの登場により、新規開発における第一選択肢ではなくなってきています。

しかし、JSPは依然として多くの既存システムで使われており、それらの保守や理解のためにはJSPの知識が不可欠です。また、Servletと連携してMVCモデルを適用し、JSTLやELを適切に利用することで、ある程度の保守性を保ったJSPベースのアプリケーションを構築することも可能です。

JSPを学ぶことは、単に古い技術を学ぶだけでなく、Servletとの関係性、Request/Response/Session/Applicationといった基本的なウェブアプリケーションのスコープ、MVCパターンといった、Javaによるウェブ開発の基盤となる知識を深めることにも繋がります。これらの知識は、Spring MVCなど他のフレームワークを学ぶ上でも非常に役立ちます。

もしあなたが既存のJSPアプリケーションに関わることになった場合や、Javaウェブ開発の歴史的な経緯や基礎を学びたいのであれば、JSPは理解しておく価値のある技術と言えるでしょう。

この記事が、JSPとは何か、どのように動作し、どのように使うのかについての理解を深める一助となれば幸いです。JSPの学習をさらに進める場合は、Servlet APIの詳細、JSTLの各種タグの詳細、そしてSpring MVCのようなモダンなJavaウェブフレームワークについて学ぶことをお勧めします。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール