Revised: 25th/Nov./2002; Since: 13th/June/2002
最初に動作確認しましょう。配備方法は紹介済みですが、ここではソースコードに注目して説明します。
HelloWorld.java:
import java.util.*;
import java.io.*;
// サーブレット関連のクラスのインポート
import javax.servlet.*;
import javax.servlet.http.*;
// サーブレットは HttpServlet を継承
public class HelloWorld extends HttpServlet {
// HTTP/1.1 GET メソッドの処理
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// 送信文字コードのセット
res.setContentType("text/html; charset=Shift_JIS");
// 出力ストリームの取得
PrintWriter out = res.getWriter();
String title = "Hello World!";
Date date = new Date();
// 出力ストリームへの書き込み
out.println("<html lang=\"ja\">");
out.println("<head><title>" + title + "</title></head>");
out.println("<body>");
out.println("<h1>" + title + "</h1>");
out.println("<p>現在時刻:" + date + "</p>");
out.println("</body></html>");
// 出力ストリームのクローズ
out.close();
}
}
本項では、ドキュメント・ルートを "C:\java\myWebApps" とします。このサーブレットのソースコードをテキスト・エディタに貼り付けて、 "C:\java\myWebApps\WEB-INF\classes" に保存してください。
最初にサーブレットで使うクラスをインポートしています。コンパイル時に $CATALINA_HOME/common/lib/servlet.jar が CLASSPATH から取得できることが条件です。後続のコンパイルの項で説明します。
import javax.servlet.*; import javax.servlet.http.*;
このサーブレットは HelloWorld というクラスの単純なものですが、あらゆるサーブレットは Servlet インタフェースを実装するか、実装クラスを継承する必要があります。通常は通信プロトコルに HTTP 使うので、 HttpServlet を継承します。
public class HelloWorld extends HttpServlet {
HttpServlet クラスのメソッドをオーバーライドしますが、単純な URL 要求は HTTP/1.1 仕様の GET メソッドを使うことになっていますので、ここでは GET メソッドを処理するメソッドである doGet() をオーバーライドします。doGet() の二つの引数はそれぞれブラウザからの「要求」と「応答」を意味し、「要求」オブジェクトを処理して、「応答」オブジェクトに書き出すことになります。
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
このサーブレットでは要求オブジェクトを処理していません。
一方、応答オブジェクトにはブラウザが受け取るコンテンツを書き出しています。通常は HTML 文書のコードになります。和文のような2バイト文字は文字セットを指定しないと文字化けします。次のコードは出力を Shift_JIS に指定しています。
res.setContentType("text/html; charset=Shift_JIS");
続いて実際に応答オブジェクトに書き出しています。そのためには、その出力ストリーム(PrintWriter型)を getWriter() メソッドで取得することになります。
PrintWriter out = res.getWriter();
このストリームへの書き出しが、ブラウザへ送られるコンテンツになるわけです。ここでは、ブラウザで閲覧する HTML コードを書き出しています。二重引用符 " は \ でエスケープする必要があるというのは、サーブレットに限らず、出力ストリームの話になります。
out.println("<html lang=\"ja\">");
サーブレットでも、最後には出力ストリームをクローズする必要があります。
out.close();
Tomcat をインストールすれば、サーブレットのコンパイルができるようになります。そのためには、 Tomcat に同梱されている servlet.jar への CLASSPATH をセットします。Tomcat 4.1 のデフォルトでは "C:\Program Files\Apache Group\Tomcat 4.1\common\lib\servlet.jar" になります。バージョンによって異なりますのでご確認ください。
CLASSPATH は、OSの環境変数 CLASSPATH にセットするか、javac オプションの -classpath の引数に与えます。
次の例は、-classpath オプションを使ったもので、Apache Tomcat のインストール・ディレクトリを、"C:\Program Files\Apache Tomcat 4.1" (デフォルト)とし、ドキュメントルートを、"C:\java\myWebApps" に設定したものです。
C:\>cd C:\java\myWebApps\WEB-INF\classes C:\java\myWebApps\WEB-INF\classes>javac -classpath "C:\Program Files\Apache Group\ Tomcat 4.1\common\lib\servlet.jar" HelloWorld.java C:\java\myWebApps\WEB-INF\classes>dir /B HelloWorld.java HelloWorld.class C:\java\myWebApps\WEB-INF\classes>
ここでは便宜上改行しましたが、コマンドライン中の改行はしてはいけません。
OS の環境変数 CLASSPATH に指定した場合は、次のように実行できます。javacがCLASSPATH変数にセットされたパスの中から、適当なものを自動的に探してくれるので、コンパイルできるのです。
C:\java\myWebApps\WEB-INF\classes>javac HelloWorld.java
server.xmlドキュメント・ルート "C:\java\myWebApps" に コンテキスト・ルート "/servletSample" でアクセスできるように、次の Context 要素を挿入します。 Tomcat 4.1.12 では 268 行目辺りになります。
<Context path="/servletSample" docBase="C:\java\myWebApps" debug="0"
reloadable="true" crossContext="true" />
ブラウザから実際のファイルシステム上のパスであるドキュメント・ルート "C:\java\myWebApps\WEB-INF\classes" へアクセスする URL のパスであるコンテキスト・ルートは "/servletSample" です。デバッグは最小要求で、アプリケーションのクラスファイル更新時には、サーバ側でもインスタンスを作り直します。
web.xml でのサーブレットの設定ドキュメントルートの中に WEB-INF フォルダを作って、その中に web.xml を作成します。ここでは、そのドキュメントルート以下の web アプリケーションの設定を記述します。ここでは、上で作ったサーブレットの名前とパスを変更してみます。
web.xml次のソースを web.xml に貼り付けて、WEB-INF の中に保存してください。保存時に文字コードが指定できれば Shift_JIS で保存してください。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app>
本稿ではドキュメント・ルートを "C:\java\myWebApps" にしているので、 web.xml のフルパスは C:\java\myWebApps\WEB-INF\web.xml になります。
これから <web-app> から </web-app> の間に記述していきます。
何も設定しなければ、サーブレットはそのクラス名で指定します。これを別の名前に変更できます。内部的に識別する名前を付けることになります。
いまサーブレットは HelloWorld クラスですが、これを Hello で参照できるように明記します。web.xml を次のように変更します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
</web-app>
任意の URL にマッピングしてみましょう。こうすると、次のようなメリットが考えられます。
web.xml を次のように変更します。
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Hello</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Hello</servlet-name>
<url-pattern>/hello.hogehoge</url-pattern>
</servlet-mapping>
</web-app>
このサーブレットへ、ドキュメントルート直下の hello.hogehoge としてアクセスできるようになりました。
http://localhost:8080/servletSample/hello.hogehoge" と入力して実行します。フルパスでのアクセスと同じサーブレットへアクセスできます。ここでは、サーブレットに名前を付けて、 URL パターンにマッピングしました。ここではドキュメントルート直下にマッピングしましたが、 "/" で区切って任意の階層の URL パターンにマッピングすることもできます。
http://localhost:8080/servletSample/hello.hogehoge の要求に対する応答:
<html lang="ja"> <head><title>Hello World!</title></head> <body> <h1>Hello World!</h1> <p>現在時刻:Sun Jun 16 01:11:37 JST 2002</p> </body></html>
ちなみに、この HTML は xml 宣言も DTD 宣言も省略されているのであまり良いものではありません。
何れにせよ、ブラウザは out.println() の引数だけを受け取るので、この応答がサーブレットによって生成されたものだとは分かりません。
例えば、この例のように HTML を出力するサーブレットならば、 *.html にマッピングすれば、クライアント側(ブラウザ)では通常の HTML 文書を見ているのと区別できない。