【コラム】

ライトニングJava

70 JSPプログラミング(1) - ディレクティブ

後藤大地  [2006/12/04]

ディレクティブとは

JSPではページのエンコーディング、レスポンスコンテンツのエンコーディング、セッションの有無、バッファに関する設定、継承元クラスの指定、エラーページの指定、スレッドモードの指定、式言語の指定、ファイルのインクルード、タグライブラリの指定など、ページ全体に関する指定、とくにサーブレットを生成する場合に必要な情報を「ディレクティブ」を使って指定する。

ディレクティブは次の形式で指定する。

<%@ ディレクティブ名 属性="値" 属性="値" ... %>

ディレクティブ名として指定できるキーワードはpage、include、taglibなど。ttaglibについては別途説明するとして、ここではpage、includeの使用例を紹介したい。

サンプルアプリケーション

ここでは次のJSPサンプルアプリケーションを使う。リスト1がメインのJSPファイルだ。pageディレクティブで指定している属性の意味はそれぞれ次のとおり。

  • page contentType - レスポンスコンテンツの種類とエンコーディングを指定。ここではHTML文書で文字コードはUTF-8を指定
  • page pageEncoding - JSPファイルのエンコーディングを指定。ここではUTF-8で記載しているのでUTF-8を指定
  • page import - JSPで使うことになるimportを指定。実際には使っていないがここでは例のためmath, io, utilをimportしている
  • page session - セッションの有無を指定。デフォルトはtrue。動作を紹介するためここではfalseを指定

リスト1 directive.jsp - ディレクティブの動作を紹介するためのJSPサンプルアプリケーション

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>JSP Directive</title>
</head>
<body>

<%-- ディレクティブ --%>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ page pageEncoding="UTF-8" %>

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

<%@ page session="false" %>

<%@ include file="import1.jsp" %>
<%@ include file="import2.jsp" %>
<%@ include file="message.jsp" %>

</body>
</html>

includeディレクティブでは、サーブレットに変換する段階で読み込むファイルを相対パスで指定する。リスト1ではためしに3つのファイルを読み込んでいる。内容はそれぞれ次のとおり。

リスト2 import1.jsp - page importディレクティブを実施 その1

<%@ page import="javax.crypto.*" %>
<%@ page import="javax.imageio.*" %>
<%@ page import="javax.naming.*" %>

リスト3 import2.jsp - page importディレクティブを実施 その2

<%@ page import="javax.net.*" %>
<%@ page import="javax.sql.*" %>
<%@ page import="javax.xml.*" %>

リスト4 message.jsp - テキストをそのまま表示している

<%@ page pageEncoding="UTF-8" %>

ディレクティブへようこそ

リスト4において、page pageEncodingディレクティブでファイルのエンコーディングを指定している点に注目してほしい。Apache Tomcat 5.5.20では、同指定を実施しないと正しく日本語を扱うことができない。JSP 1.2ではpage pageEncodingディレクティブを1つしか指定できなかったため、includeされるファイルのエンコーディングを指定されたpageEncodingの内容に沿って解釈していたが、JSP 2.0からは複数指定できるようになったため、ファイルごとに判別が実施されるようになった。ただし、このあたりの実装は採用しているWebアプリケーションサーバがどういった実装になっているかにも左右されるので、個別に確認してほしい。

デプロイ

JSPはWEB-INFやデプロイメントディスクリプタは不要。そのままWebアプリケーションのwebappsディレクトリにコピーすればいい。

図1 Apache Tomcat 5.5.20へのデプロイ例

準備が整ったらWebアプリケーションを起動する。

サンプルを実行

http://127.0.0.1:8080/directive/directive.jspにアクセスする。図2のような実行画面が得られるだろう。表示されているHTML文書は図4のようになっている。

図2 JSPサンプルアプリケーションの実行例

図3 Webブラウザが表示しているHTML文書

ソースコードからディレクティブの変換内容を知る

JSPサンプルアプリケーションを実行したら(Webアプリケーションサーバによってはデプロイした段階ですでに生成される)、生成されるJavaソースコードを見てみよう。ディレクティブがどのようなソースコードとして展開されるかがよくわかる。

図4 JSPサンプルアプリケーションの実行例

page contentTypeディレクティブの指定は、リスト5のようにレスポンスのコンテンツタイプを指定するコードに変換される。page pageEncodingは、JSPファイルをJavaソースコードファイルに変換する場合にファイルそのもののエンコーディングとして利用される。

リスト5 page contentTypeディレクティブの指定

      response.setContentType("text/html; charset=UTF-8");

page importディレクティブはリスト6のように、page sessionディレクティブの指定はリスト7のようになる。それぞれ直接的にソースコードに展開されていることがわかる。

リスト6 page importディレクティブの指定

import java.math.*;
import java.io.*;
import java.util.*;

リスト7 page sessionディレクティブの指定

pageContext = _jspxFactory.getPageContext(this, request, response,
                                          null, false, 8192, true);

includeディレクティブで指定されたファイルも同様に読み込まれて変換されていることがわかる。includeディレクティブで読み込んだpage importディレクティブはそれぞれリスト8、リスト9のように変換され、includeディレクティブで読み込んだテキストメッセージはリスト10のようにテキストを出力する内容に変換されている。

リスト8 page importディレクティブで指定したpage importディレクティブを含んだファイルの内容 その1

import javax.crypto.*;
import javax.imageio.*;
import javax.naming.*;

リスト9 page importディレクティブで指定したpage importディレクティブを含んだファイルの内容 その2

import javax.net.*;
import javax.sql.*;
import javax.xml.*;

リスト10 page importディレクティブで指定したテキストメッセージ

      out.write("ディレクティブへようこそ");

ためしにリスト4ファイルからpage pageEncodingディレクティブの指定を抜いて同様の処理を実行してみてほしい。Apache Tomcat 5.5.20のようなWebアプリケーションサーバなら、ファイルがシステムデフォルトのエンコーディングだと解釈して、ここで表示される文字列が化けるはずだ。

リスト11に変換後の全ソースコードを掲載しておく。ディレクティブがどのようなソースコードに変換されるかよくわかる。

リスト11 Servletコードに変換されたJSPサンプルアプリケーション - Apache Tomcat 5.5.20の場合

package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.math.*;
import java.io.*;
import java.util.*;
import javax.crypto.*;
import javax.imageio.*;
import javax.naming.*;
import javax.net.*;
import javax.sql.*;
import javax.xml.*;

public final class directive_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static java.util.List _jspx_dependants;

  static {
    _jspx_dependants = new java.util.ArrayList(3);
    _jspx_dependants.add("/import1.jsp");
    _jspx_dependants.add("/import2.jsp");
    _jspx_dependants.add("/message.jsp");
  }

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    JspFactory _jspxFactory = null;
    PageContext pageContext = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      _jspxFactory = JspFactory.getDefaultFactory();
      response.setContentType("text/html; charset=UTF-8");
      pageContext = _jspxFactory.getPageContext(this, request, response,
                  null, false, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("JSP Directive\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write('\n');
      out.write('\n');
      out.write('\n');
      out.write('\n');
      out.write('\n');
      out.write('\n');
      out.write("\n");
      out.write("\n");
      out.write("ディレクティブへようこそ");
      out.write("\n");
      out.write("\n");
      out.write("\n");
      out.write("\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          out.clearBuffer();
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
      }
    } finally {
      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

このようにJSPプログラミングを実施する場合、変換後のソースコードがどうなっているのかチェックしてみるといい。JSPは基本的にはServletなので、変換後のソースコードを読めば動作も一目瞭然だ。

提供:毎日就職ナビ

会員登録はこちら

学生のための就職情報サイト「毎日就職ナビ」。6,000社以上の新卒採用情報が常時掲載され、社内の雰囲気が伝わる情報画面、さまざまな項目での会社検索、エントリーや説明会検索など、機能も充実。無料適職診断、就活Q & A、エントリーシート添削講座など、就職活動に役立つ記事も満載です。研究者、エンジニアを目指す学生の方々も是非エントリーしてください。お待ちしています!

毎日コミュニケーションズ 就職情報事業本部はプライバシーマークを取得しています。

    新着記事

    特設サイトの情報

    人気記事

    一覧

    イチオシ記事

    新着記事

    特別企画

    一覧