普段C#やPHP、Pythonを使っているエンジニアがJavaを勉強して学んだことを紹介します。今回は第2回目で、Webアプリケーションについてです。

第一回目の記事: 他言語エンジニアのためのJava入門 1 – コンパイルとクラスパス

JavaでWebアプリケーションを作る方法を調べると、Spring Boot を使った方法が多く検索されます。実際 Spring Boot はデファクトスタンダードになっているようで、実際のプロジェクトでは何かしらのフレームワークを使って開発することが多いと思いますが、その裏側の仕組みがわからないとなかなか理解しずらいように思いました。

そのため今回は、JavaのWebアプリケーションの仕組みである「サーブレット」を紹介します。

第一回の記事は普通のコンソールアプリケーションを作りましたが、Webアプリケーションではブラウザとやり取りするHTTPリクエストやレスポンスを操作する必要があるなど、追加の機能が必要となります。PHPではコアライブラリにWebの機能が組み込まれていますが、他の言語、例えばC#ではASP.NETという専用のライブラリが必要になります。

Javaでは、「サーブレット」というのがこのWeb用のライブラリとなります。具体的には”javax.servlet” パッケージと “javax.servlet.http” パッケージのことで、このパッケージを使うとWebアプリケーションが作れます。なお「サーブレット」という言葉自体はライブラリ自体を指すこともあれば、サーブレットライブラリを使ったJavaアプリケーションを指すこともあるので少しややこしいのですが、今回は両方の意味で使いたいと思います。

(なおJavaでWebアプリケーションを調べると、サーブレットと一緒に「JSP」というものも出てきます。JSPはJavaのテンプレートエンジンのようなもので、昔はサーブレットにロジックを書き、JSPにHTMLを書く、という構成が多かったようです。ただSpring Bootでは別のテンプレートエンジンが主流ですし、JSPも内部的にはサーブレットとしてコンパイルされるため、今回はJSPの説明は割愛します)

サーブレットはWebアプリケーションですので、コマンドラインから直接実行することはできません。Webサーバーと連携する実行環境が必要です。PHPではmod_php、RubyならPassenger、C#ではIIS (のASP.NETハンドラー) が実行環境となるように、サーブレットでは「サーブレットコンテナ」が実行環境となります。

サーブレットコンテナ

「サーブレットコンテナ」は、サーブレットライブラリを使って作られたJavaアプリケーションの実行環境です。

実際の環境では、

  1. WebサーバーがHTTPリクエストを受け、
  2. それをサーブレットコンテナに転送し、
  3. サーブレットコンテナが処理結果をWebサーバーに返し、
  4. Webサーバーがクライアントに結果を返す

という流れで動作します。

第一回でお話したように、Javaでは言語の開発元は仕様のみを公開し、実装は各ベンダーが行うというスタイルを取っていて、サーブレットコンテナにとっても同様です。有名なサーブレットコンテナは「Tomcat」というもので、Spring Bootでも裏側でTomcatを使っています (もちろん他のサーブレットコンテナもあり、設定で変更できます)。

Tomcat自体をWebサーバーとして使用することもできますが、機能が多くないためあくまでサーブレット用のアプリケーションサーバーとして使用することが多いようです。Webサーバーと連携させるには、例えばApacheなら mod_proxy を使って、Tomcatが開いているポートにリクエストを転送する、という設定を行います。

今回のサンプルではTomcatを使っています。試す場合はTomcatをダウンロードして起動できるようにしておいてください。(もし難しければXAMPPなどのパッケージが便利だと思います)

サーブレットの実装

それではサーブレットの実装方法を見ていきましょう。まず簡単なJavaプログラムを作成しコンパイルします。

HelloWorld.java

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException{

    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head>");
    out.println("<title>Hello!</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<h1>Hello!</h1>");
    out.println("</body>");
    out.println("</html>");
  }
}

これをコンパイルして、.classファイルを作成します。この時、クラスパスにサーブレットライブラリのパスを指定しないとコンパイルが通りませんので注意してください。サーブレットライブラリはTomcatに含まれるものを使います。

$ javac --classpath "/Tomcatルートフォルダ/lib/servlet-api.jar" HelloWorld.java
  > HelloWorld.class が出力される

この.classファイルをTomcatに配置します。配置する時のフォルダ構成はサーブレットの仕様で決まっています。最低限必要なフォルダ/ファイルは以下のようになります。

フォルダー構成

- ROOT
  - WEB-INF
    - web.xml
    - classes
      - HelloWorld.class

サーブレットはWEB-INFフォルダを含む必要があり、その中にweb.xmlというサーブレットの構成ファイルが必ず必要です。そしてJavaの.classファイルはWEB-INF/classesフォルダーの中に置きます。

この他のファイル (例えば画像ファイル、CSS、Javascript、htmlファイルなど)はROOTフォルダ以下のどこに置いても大丈夫です。

web.xmlファイルにはサーブレットの定義と、どのURLにアクセスされた時にどのサーブレットを実行するか、という情報を定義します。

web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
  version="2.4">

  <servlet>
    <servlet-name>helloworld</servlet-name>
    <servlet-class>HelloWorld</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>helloworld</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>  
</web-app>

<servlet>でサーブレットライブラリを実装した.classファイルに名前を付け、<servlet-mapping>でURL (上記の例ではルートURL) とマッピングしています。この設定で、URLルートにアクセスがあった場合に、HelloWorld.classに定義されたサーブレットが実行されるようになります。

それでは試してみましょう。Tomcatを起動し、ブラウザで http://localhost:8080/ とルートURLにアクセスしてみてください (ポート番号は環境によって違うかもしれませんのでご注意ください)。Hello! と表示されれば成功です。

面倒な手順を無くすために

まとめると、JavaでWebアプリケーションを作る時、

  1. まずサーブレットライブラリを実装したJavaプログラムをコンパイルし、
  2. サーブレットの構成ファイルである web.xml を定義し、
  3. サーブレットの仕様にそってフォルダを構成し、
  4. Tomcatに配置する

という手順が必要になります。URLパス毎にサーブレットクラスを実装し、web.xmlでURLとサーブレットをそれぞれマッピングしなければならないので、大きなWebサイトを作る場合、メンテナンスが非常に面倒になります。

そのような面倒を一切省いてWebアプリケーションを開発できるようにしたのがSpring Bootでした。そのため非常に人気があるのですが、裏の仕組みが見えなくなった分、初心者にはわかりにくくなった部分もあると思います。応用を利かせようとする時は、裏でサーブレットという仕組みが動いていることを意識してみてください。