tomcat
簡単なServlet
Webアプリケーションの作成
tomcatは C:\Users\nitta\Documents\tomcat8 (Windowsの場合)
または
/Users/nitta/Documents/tomcat9 (macOS の場合)
にインストールされていて、
環境変数CATALINA_HOMEはこのpathを保持しているものとする。
環境変数の値を表す文法はOS(Shell)によって異なり、
Unix系 (macOS, Linux等)では
${CATALINA_HOME},
Windows では
%CATALINA_HOME%
である。
以下の記述では、Unix系の記法を採用して、Tomcat 8 がインストールされたパスを
${CATALINA_HOME}
で表している。自分の環境に適宜読み替えて理解してほしい。
Webアプリケーションは ${CATALINA_HOME}/webapps の下に配置する。
ここでは entry というWebアプリケーションを作成する例で説明する。
webapps フォルダの中に entry フォルダを作成する
エクスプローラで、
${CATANLINA_HOME}\webassps\entry
フォルダを作成する。
注意
Tomcatは起動時の
${CATALINA_HOME}/webapps/
以下の状態をキャッシュしている。
そのため、webappsより下のファイルを変更した場合は、
一旦Tomcatを停止して
(${CATALINA_HOME}\bin\shutdown.bat をエクスプローラ上でクリック)、
その後でTomcatを起動し直す
(${CATALINA_HOME}\bin\startup.bat をエクスプローラ上でクリック)
必要がある。
HTMLドキュメントを置く
[ファイル配置]
${CATALINA_HOME}/webapps/entry/hello.html
${CATALINA_HOME}/webapps/entry/hello.html |
<html>
<head>
<title>html example</title>
</head>
<body>
<h2>Hello</h2>
This is HTML.
</body>
</html>
|
[ブラウザでアクセスするURL]
http://localhost:8080/entry/hello.html
サブディレクトリを作ってみる
[ファイル配置]
${CATALINA_HOME}/webapps/entry/sub/sub.html
${CATALINA_HOME}/webapps/entry/sub/sub.html |
<html>
<head>
<title>Sub</title>
</head>
<body>
<h2>Sub</h2>
This is Sub.
</body>
</html>
|
[ブラウザでアクセスするURL]
http://localhost:8080/entry/sub/sub.html
最も簡単なサーブレット
[ファイル配置]
${CATALINA_HOME}/webapps/entry/WEB-INF/src/HelloServlet.java ←作成する
/classes/HelloServlet.class←コンパイラで生成する
クラスファイル(拡張子が.classのファイル)は
「${CATALINA_HOME}/webapps/Webアプリケーション名/WEB-INF/classes」
フォルダに置かなくてはいけない。
ソースファイル(拡張子が.javaのファイル)はどこに置いても構わないが、
ここでは
「${CATALINA_HOME}/webapps/Webアプリケーション名/WEB-INF/src」
フォルダに置くことにする。
HelloServlet.javaで記述するのは以下の点である。
- javax.servlet.http.HttpServletを継承する(extends)
- doGet()メソッドをオーバーライド(override)する
コンパイル時には、Javaの標準でないAPIを利用するので、
servlet-api.jarを環境変数CLASSPATHに含めておく必要がある。
環境変数名: CLASSPATH
値: .;C:\Users\nitta\Documents\tomcat8\lib\servlet-api.jar;その他のパス
(または .;%CATALINA_HOME%\lib\servlet-api.jar;その他のパス ) ←他の環境変数を使って記述してもよい
環境変数を設定した後で起動したプログラム(たとえばコマンドプロンプト等)では、CLASSPATH変数に値が設定されている。
CLASSPATH変数に値を設定する場合は、必ず '.' (カレント・ディレクトリ)も先頭に含めておくこと。
複数の値を設定する場合は ';' (セミコロン)でつなぐ。
${CATALINA_HOME}/webapps/entry/WEB-INF/src/HelloServlet.java |
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
out.println("Hello");
}
}
|
コンパイルは次のように指定する。
-dオプションによって .classファイルを生成する先のフォルダを指定する(classesフォルダは前もって作っておくこと)。
また -sourcepathオプションは、コマンドラインで指定したファイル以外が必要になった
ときに探すフォルダである(今回のコンパイルでは必要ないが、後で必要になる場合がある)。
HelloServlet.javaのコンパイル |
C:\Users\nitta> echo %CLASSPATH% ← CLASSPATH環境変数を表示する
.;C:\Users\nitta\Documents\java\lib\mariadb-java-client-2.7.0.jar;C:\Users\nitta\Documents\tomcat8\lib\servlet-api.jar
C:\Users\nitta> cd Documents/tomcat8/webapps/entry ← entryに移動する
C:\Users\nitta\Documents\tomcat8\webapps\entry> cd WEB-INF ← WEB-INFに移動する
C:\Users\nitta\Documents\tomcat8\webapps\entry\WEB-INF> javac -encoding utf8 src/HelloServlet.java -d classes -sourcepath src ← コンパイルする
|
web.xmlの記述
[ファイル配置]
${CATALINA_HOME}/webapps/entry/WEB-INF/classes/HelloServlet.class
/src/HelloServlet.java
/web.xml ←このファイルを作成する
web.xmlは、Webアプリケーションの動作を記述するためのファイルで、
Deployment Descriptor (配備記述子)と呼ばれる。
このファイルはXML形式で表現する。
web.xml |
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
metadata-complete="false">
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
|
- servlet...「サーブレット名」と「クラスファイル」を対応づける
- servlet-name ... サーブレットの名前
- servlet-class ... サーブレットのクラス
- servlet-mapping ... 「URLのパターン」と「サーブレット名」を対応づける
- servlet-name ... サーブレットの名前
- servlet-url ... サーブレットのURLパターン
url-patternの記述 | 呼び出すときのURLの指定 |
/aaa | http://マシン名:ポート番号/entry/aaa |
/aaa/bbb | http://マシン名:ポート番号/entry/aaa/bbb |
/aaa/bbb.ccc | http://マシン名:ポート番号/entry/aaa/bbb.ccc |
url-patternの記述には先頭に'/'が必要なことに注意すること。
${CATALINA_HOME}/webapps/examples/WEB-INF/web.xmlを参考に記述すること。
web.xmlの最初のweb-appタグに関する記述はタイプミスをしやすいので、
エディタでコピーしてしまう方がよい。
コピーしたあと metadata-complete要素の値を
"true"から"false"へ変更しておくこと。
metadata-complete要素を"false"にしておくと、
Servlet3.0テクノロジーで導入された
web fragmentやAnnotationの機能を使うことができる。
(これらの機能については次週以降に述べる。)
[ブラウザでアクセスするURL]
http://localhost:8080/entry/HelloServlet
tomcatのオートリロードの設定
ここで HelloServlet.javaを書き換えてみる。
HelloServlet.javaの書き換え |
*** ../webapps/entry/WEB-INF/src/HelloServlet.java Thu Nov 24 12:08:44 2016
--- ../webapps/entry/WEB-INF/src/HelloServlet2.java Wed Jul 27 17:40:14 2011
***************
*** 5,10 ****
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
! out.println("Hello");
}
}
--- 5,10 ----
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
! out.println("Hello2");
}
}
|
このファイルをコンパイルし直した後で、ブラウザで先ほどのURL
(http://マシン名:ポート番号/entry/HelloServlet)
にアクセスし直しても(or reloadしても)表示は変わらないはずである。
Tomcatはサーブレットのクラスファイルを読み込んだ後は
キャッシュしてしまうので、クラスファイルを変更しても
その変更は即座には動作に反映されない。
(Tomcatを再起動すれば反映される。)
クラスファイルを変更する度にTomcatを再起動するのは煩わしいので、
以下のようにオートリロードの設定をしておくとよい。
META-INF の下に context.xmlというファイルを作成する。
[ファイル配置]
${CATALINA_HOME}/webapps/entry/META-INF/context.xml
(注意) META-INF/の下であることに注意。WEB-INF/の下ではない。
${CATALINA_HOME}/webapps/entry/META-INF/context.xml |
<Context reloadable="true" />
|
「オートリロード」機能が有効になったことを確認しておくこと。
- Tomcatを再起動する。
- ブラウザでhttp://マシン名:ポート番号/entry/HelloServletにアクセスして
Hello2と表示されることを確認する。
- HelloServlet.javaの表示される文字列を"Hello3"と書き換えてコンパイルし直す。
- ブラウザでhttp://マシン名:ポート番号/entry/HelloServlet にアクセスして、
Hello3と表示が変わることを確認する。
- tomcatがclassファイルが変更されたことを検知するのに、しばらく(数分?)かかる場合がある。
パッケージ付きのサーブレット
[ファイル配置]
${CATALINA_HOME}/webapps/entry/WEB-INF/src/foo/BarServlet.java
${CATALINA_HOME}/webapps/entry/WEB-INF/src/foo/BarServlet.java |
package foo;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class BarServlet extends HttpServlet {
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
out.println("bar");
}
}
|
web.xmlへの記述の追加 |
*** ../webapps/entry/WEB-INF/web.xml.01 Fri Nov 18 19:12:38 2016
--- ../webapps/entry/WEB-INF/web.xml.02 Fri Nov 18 19:12:55 2016
***************
*** 9,16 ****
--- 9,24 ----
<servlet-name>HelloServlet</servlet-name>
<servlet-class>HelloServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>BarServlet</servlet-name>
+ <servlet-class>foo.BarServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>BarServlet</servlet-name>
+ <url-pattern>/BarServlet</url-pattern>
+ </servlet-mapping>
</web-app>
|
BarServlet.javaのコンパイル |
> cd %CATALINA_HOME%\webapps\entry\WEB-INF
> javac -encoding utf8 src\foo\BarServlet.java -d classes -sourdepath src ← fooパッケージに属するソースをコンパイルする
> dir classes\foo
...
2020/10/30 16:56 621 BarServlet.class ← classes/foo/の下にclassファイルが生成されている
...
|
[ブラウザでアクセスするURL]
http://localhost:8080/entry/BarServlet
他のクラスを使うサーブレット
[ファイル配置]
${CATALINA_HOME}/webapps/entry/WEB-INF/src/Oracle.java
OracleServlet.java
運勢を占うサーブレットを作る。
乱数を発生させて、その結果に応じて異なる文字列を返す getResult()メソッドを持つ
Oracleクラスを作成する。
${CATALINA_HOME}/webapps/entry/WEB-INF/src/Oracle.java |
import java.util.*;
public class Oracle {
private static Random random = new Random();
public String getResult() {
int n = random.nextInt(10);
if (n < 2 ) return "very good";
else if (n < 5) return "good";
else if (n < 7) return "bad";
else return "very bad";
}
}
|
Oracleクラスを呼び出すサーブレットとしてOracleServletクラスを作成します。
${CATALINA_HOME}/webapps/entry/WEB-INF/src/OracleServlet.java |
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class OracleServlet extends HttpServlet {
public void doGet(HttpServletRequest req,HttpServletResponse res)
throws IOException, ServletException {
PrintWriter out = res.getWriter();
Oracle ora = new Oracle();
String result = ora.getResult();
out.println("Your fortune is " + result);
}
}
|
web.xmlへの記述の追加 |
*** ../webapps/entry/WEB-INF/web.xml.02 Fri Nov 18 19:12:55 2016
--- ../webapps/entry/WEB-INF/web.xml.03 Fri Nov 18 19:13:08 2016
***************
*** 13,18 ****
--- 13,22 ----
<servlet-name>BarServlet</servlet-name>
<servlet-class>foo.BarServlet</servlet-class>
</servlet>
+ <servlet>
+ <servlet-name>OracleServlet</servlet-name>
+ <servlet-class>OracleServlet</servlet-class>
+ </servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/HelloServlet</url-pattern>
***************
*** 21,24 ****
--- 25,32 ----
<servlet-name>BarServlet</servlet-name>
<url-pattern>/BarServlet</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>OracleServlet</servlet-name>
+ <url-pattern>/OracleServlet</url-pattern>
+ </servlet-mapping>
</web-app>
|
コンパイルするときはOracleクラスのソースの置き場所を示すために
必ず -sourcepathオプションを指定する必要がある。
OracleServlet.javaのコンパイル |
> cd %CATALINA_HOME%
> cd webapps/entry/WEB-INF
> javac -encoding utf8 src\OracleServlet.java -sourcepath src -d classes
> dir classes\Oracle*class
...
classes/Oracle.class
classes/OracleServlet.class
...
|
[ブラウザでアクセスするURL]
http://localhost:8080/entry/OracleServlet ←reloadする度に表示が変わる。