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アプリケーションを作成する例で説明する。
Tomcatは起動時の ${CATALINA_HOME}/webapps/ 以下の状態をキャッシュしている。 そのため、webappsより下のファイルを変更した場合は、 一旦Tomcatを停止して (${CATALINA_HOME}\bin\shutdown.bat をエクスプローラ上でクリック)、 その後でTomcatを起動し直す (${CATALINA_HOME}\bin\startup.bat をエクスプローラ上でクリック) 必要がある。
[ファイル配置] ${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のファイル)は
「
HelloServlet.javaで記述するのは以下の点である。
コンパイル時には、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% |
[ファイル配置] ${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> |
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
ここで 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" /> |
「オートリロード」機能が有効になったことを確認しておくこと。
[ファイル配置] ${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 |
[ブラウザでアクセスする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% |
[ブラウザでアクセスするURL] http://localhost:8080/entry/OracleServlet ←reloadする度に表示が変わる。