Servletは、HttpServletというクラスを継承して、必要なメソッドをオーバーライドしたクラスです。CGIと同じように、プログラムの中からHTMLを出力できます。
JSPのところで、サンプル1,サンプル2, ...サンプル5のような出力をするloop.jspというサンプルプログラムを示しました。ここでは、同じ働きをするServletのプログラムを見てみましょう。
// LoopServlet // サンプル1, サンプル2, ... サンプル5 // とブラウザに表示する Servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class LoopServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } private void doIt(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=Shift_JIS"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>LoopServlet</title>"); out.println("</head>"); out.println("<body>"); for (int i = 1; i <= 5; i++) { out.print("<p>サンプル"); out.println(i); out.print("</p>"); } out.println("</body>"); out.println("</html>"); } }
Servletのメソッドは、HTTPのリクエストメソッドと深く関係しています。HTTPのGETメソッドに対してはServletのdoGetメソッドが呼び出され、POSTメソッドに対してはServletのdoPostメソッドが呼び出されます。いずれのメソッドにも、ブラウザからの要求を表すHttpServletRequest型のオブジェクトと、Servletからの応答を表すHttpServletResponse型のオブジェクトが引数に含まれています。このServletでは、いずれのメソッドも、doIt(request, response)というメソッドに処理をまかせています。
またHTMLの出力は、次の手順になります。まず、HttpServletResponse型のオブジェクトであるresponseからPrintWriterオブジェクトを取り出します。次に、そのオブジェクトのprintln()メソッド、あるいはprint()メソッドを実行して、HTMLを書き出します。HTTPでは応答によってHTMLを返すので、応答を処理するHttpServletResponseを使うのです。
PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>LoopServlet</title>");
次の部分で、サンプル1,サンプル2, ...サンプル5と出力しています。
for (int i = 1; i <= 5; i++) { out.print("<p>サンプル"); out.println(i); out.print("</p>"); }
もう1つのサンプルプログラムを見てみましょう。現在日時を表示するServletである、DateServlet.javaです。df.format()メソッドを実行することによって、現在の日時を出力しています。
// DateServlet // 現在の日時をブラウザに表示する Servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.Date; import java.text.DateFormat; public class DateServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } private void doIt(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=Shift_JIS"); Date d = new Date(); DateFormat df = DateFormat.getDateTimeInstance(); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>DateServlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>"); out.println("いまは"); out.println("<br />"); out.println(df.format(d)); out.println("<br />"); out.println("です。"); out.println("<br />"); out.println("</body>"); out.println("</html>"); } }
次のサンプルは、要求のヘッダ情報をブラウザに表示するServletです。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import java.util.Enumeration; public class PrintHeadersServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } private void doIt(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Enumeration enum = request.getHeaderNames(); response.setContentType("text/html; charset=Shift_JIS"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>ヘッダの一覧</title>"); out.println("</head>"); out.println("<body>"); out.println("<ul>"); while (enum.hasMoreElements()) { out.print("<li>"); String name = (String)enum.nextElement(); out.print(name + ": "); out.print(request.getHeader(name)); out.println("</li>"); } out.println("</ul>"); out.println("</body>"); out.println("</html>"); } }
このサンプルでは、HttpServletRequest型のオブジェクトrequestから、要求のヘッダ名のリストを取得しています。HTTPの要求を処理するのがHttpServletRequestであるのがポイントです。
Enumeration enum = request.getHeaderNames();
また、HttpServletResponse型のオブジェクトからPrintWriterを取得し、そのPrintWriterに対してHTMLを出力しています。HTTPでは応答によってHTMLを返すので、応答を処理するHttpServletResponseを使うのです。
PrintWriter out = response.getWriter(); out.println("<html>");
このサンプルは、次のような出力になります。
* host: localhost:8080 * user-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:0.9.2) Gecko/20010726 Netscape6/6.1 * accept: text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, image/png, image/jpeg, image/gif;q=0.2, text/plain;q=0.8, text/css, */*;q=0.1 * accept-language: ja * accept-encoding: gzip,deflate,compress,identity * accept-charset: Shift_JIS, utf-8;q=0.66, *;q=0.66 * keep-alive: 300 * connection: keep-alive
Servletでは、HttpServletRequestを使ってクエリーを処理します。
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class NameServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doIt(request, response); } private void doIt(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("Shift_JIS"); response.setContentType("text/html; charset=Shift_JIS"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println("<head>"); out.println("<title>入力された名前について</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>"); out.println("姓: "); out.println(request.getParameter("familyName")); out.println("</p>"); out.println("<p>"); out.println("名: "); out.println(request.getParameter("givenName")); out.println("</p>"); out.println("</body>"); out.println("</html>"); } }
JSPと同じように、request.getParameter()というメソッドを使って、パラメータの値を出力しています。
out.println(request.getParameter("familyName"));
Servletのプログラムに含まれている次のパッケージは、J2SEには含まれていません。
そこで、Tomcatに含まれているライブラリをclasspathに含めてコンパイルする必要があります。
Windowsでは、次のようにしてコンパイルを実行します。
java -classpath "%CATALINA_HOME%\common\lib\servlet.jar" LoopServlet.java
classpathの値が""で囲われているのが不思議に思えるかもしれません。
"%CATALINA_HOME%\common\lib\servlet.jar"
これは、%CATALINA_HOME%の値にスペースが入っている時のための対策です。筆者の環境ではCATALINA_HOMEの値は次のようにスペースが入っているので、""で囲うことが必要になります。
C:\>echo %CATALINA_HOME% C:\Program Files\Apache Group\Tomcat 4.1
%CATALINA_HOME%\testというフォルダがあったとすると、その中のWEB-INF/classesフォルダにServletを置きます。Servletは、コンパイル済みのクラスファイルを配置します。
先のサンプルのServletを追加したときの、WEB-INFフォルダ以下の構成を示します。
WEB-INF/ --- web.xml |- classes/ --- LoopServlet.class |- DateServlet.class |- lib/
Servletを使うときには、WEB-INFフォルダの中にあるweb.xmlを編集して、Servletに関する情報を記述する必要があります。JSPの場合は、web.xmlを編集する必要はありませんが、このファイルそのものが無ければ動作しません。
<?xml version="1.0" encoding="ISO-8859-1"?> <!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> <display-name>Servlet_and_JSP_Samples</display-name> <description> Servlet and JSP Samples </description> <servlet> <servlet-name>loop</servlet-name> <servlet-class>LoopServlet</servlet-class> </servlet> <servlet> <servlet-name>date</servlet-name> <servlet-class>DateServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>loop</servlet-name> <url-pattern>/loop</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>date</servlet-name> <url-pattern>/date</url-pattern> </servlet-mapping> </web-app>
Servletに関する情報の例として、LoopServletに関する部分を抜き出してみましょう。
<servlet> <servlet-name>loop</servlet-name> <servlet-class>LoopServlet</servlet-class> </servlet> (中略) <servlet-mapping> <servlet-name>loop</servlet-name> <url-pattern>/loop</url-pattern> </servlet-mapping>
前半のservletタグには、servlet-nameとservlet-classという2つの要素が含まれています。servlet-classでは、Servletのクラス名を指定します。ここでは、LoopServletになります。servlet-nameでは、このServletに対する名前を指定します。ここでは、"loop"という名前を付けています。
後半のservlet-mappingタグには、servlet-nameとurl-patternという2つの要素が含まれています。servlet-nameは、先のservletタグの中で指定した名前です。url-patternに、このServletにアクセスするときのURLを記述します。ここでは、"/loop"となることを示しています。
まず、Tomcatを起動します。Tomcatがlocalhost上の8080番ポートで動いているとします。
LoopServletやDateServletには、次のURLでアクセスします。先のweb.xmlファイルで指定したURLを使っています。
http://localhost:8080/test/loop http://localhost:8080/test/date