← 解説「Servlet・WAR・アプリケーションサーバ」に戻る
サンプルコードで身につける: Servlet・WAR・アプリケーションサーバ
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1WAR の中身を一覧する
を1だけ入れた demo.war の中身です。クラスは に、対応表は に入ります。 の下はクライアントへ直接返さない決まりで、この実験でも /demo/WEB-INF/web.xml へのリクエストは 404 でした。
META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/classes/WEB-INF/classes/hello/WEB-INF/classes/hello/HelloServlet.classWEB-INF/web.xml
2web.xml — URL とクラスの対応表
どの URL でどのクラスを呼ぶかを、コードの外の XML に書きます。はこのファイルを読んで hello.HelloServlet のを作り、/hello に来たリクエストを渡します。Java のコードには URL が1つも出てきません。
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" version="6.1"><servlet><servlet-name>hello</servlet-name><servlet-class>hello.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping></web-app>
3Tomcat が WAR を見つけて読み込むログ
demo.war を に置いて を起動したときのログです(時刻と名は省略)。配備しているのは Tomcat の側で、Servlet のは起動時の ではなく、リクエストを処理する(exec-1)で呼ばれました。84 ms や 116 ms は1クラスだけの をこの環境で動かした値で、Tomcat 一般の値ではありません。
INFO [main] ...VersionLoggerListener.log Server version name: Apache Tomcat/11.0.26INFO [main] ...VersionLoggerListener.log JVM Version: 25.0.4.1+1-LTS...INFO [main] ...StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/11.0.26]INFO [main] ...HostConfig.deployWAR Deploying web application archive [/usr/local/tomcat/webapps/demo.war]INFO [main] ...HostConfig.deployWAR Deployment of web application archive [/usr/local/tomcat/webapps/demo.war] has finished in [84] ms...INFO [main] ...Catalina.start Server startup in [116] milliseconds[HelloServlet] constructor called by http-nio-8080-exec-1
41つのインスタンスを複数のスレッドが通る
下の出力は、Tomcat に4本のリクエストを同時に送ったときの実物です。instance は4本とも同じで、thread だけが違います。コードは同じ形を素の Java で再現したもので、スレッドを4本持つ側(コンテナ役)が、1つだけ作ったインスタンスのを同時に呼びます。
thread = http-nio-8080-exec-8instance = 1141094684thread = http-nio-8080-exec-7instance = 1141094684thread = http-nio-8080-exec-9instance = 1141094684thread = http-nio-8080-exec-1instance = 1141094684
Java
5対比: Node は自分で listen する
Node のサーバは、自分のプログラムの中でサーバを作り、自分で listen を呼んでポートを開きます。起動するのは自分のプロセスで、入れ物になる別のサーバはありません。Servlet の形では、この createServer と listen に当たる部分をコンテナが持っていて、アプリが書くのはコールバックに当たる だけです。
// server.js — node server.js で起動する
const http = require("node:http");
// リクエストを処理する関数を渡してサーバを作る
const server = http.createServer((req, res) => {
res.setHeader("Content-Type", "text/plain; charset=utf-8");
res.end("hello from node");
});
// ポートを開くのは自分のコード
server.listen(3000);
// Servlet と並べると
// Node : 自分のプロセスが listen する。main に当たるのは自分のファイル
// Servlet : listen するのはコンテナ。自分のクラスに main は無い