この記事ではJavaで作成したWebアプリケーションの動作と「アノテーション」というものについて説明する。
目次
Webアプリケーションの設定とは
最初にWebアプリケーションがどのように動いているかを簡単に説明しよう。ユーザがブラウザの画面に表示された絵や文章とリンクしたURL(http://www.linuxacademy.ne.jp/servlet など)を選ぶか、直接ブラウザにURLを入力すると、選んだリンク先の画面がブラウザに表示される。この時、何が起きているかと言うと、ブラウザからWebサーバーに送られてきたリクエストに対してレスポンスを返すよう設定されたサーブレットが起動されている。そして、そのサーブレットが返すレスポンスによって、次の画面が表示される。このリクエストとサーブレットの関係を設定することを「Webアプリケーションの設定」と呼んでいる。
Webアプリケーションを動かすためには、ただサーブレットクラスを作成するだけでは足りない。クライアントからのリクエストに対応するサーブレットを設定することをマッピング(紐付け)と呼ぶ。
このマッピングのために必要な基本的な情報は次の通りである。
- URLパス:サーブレットを起動するためのパス
例:http://www.linuxacademy.ne.jp/servlet
- コンテキストルート(context-root):;サーブレットやHTMLやWebアプリケーションの設定などが入っている一番上位のディレクトリ
例:C:\WebApplication
- サーブレットの完全修飾名:パッケージ名とクラス名の両方を持つクラス名
例:sample.Servlet
クライアントがリクエストにURLパスを指定してWebサーバーに送ると、WebサーバーにあるWebコンテナが対応するサーブレットにリクエストを渡してくれる。この時、URLパスの中のurl-patternからサーブレットへのマッピング情報は、アノテーションとしてサーブレットクラスのコードの中に宣言されている。次の図はURLパスからどのように、サーブレットへマッピングされるかを示している。
アノテーションの宣言の仕方
アノテーションとは、プログラムの一部ではないけれど、プログラムについての情報を提供するものである。サーブレットのプログラミングでは、アノテーションによってURLパスとサーブレットとのマッピング情報を宣言することができる。
Java EEの最新のバージョンでは、マッピングのためにweb.xmlを使わなくてもアノテーションを使うことができる。web.xmlを使うか、アノテーションを使うかは選択できる。
書き方の基本は簡単だ。
@WebServlet("/url-pattern")
次の図は、どのようにurl-patternがサーブレットのコードにマッピング情報として宣言されているかを示している。サーブレットのクラス定義の直前にurl-patternがアノテーション:@WebServletによって記述されている。これによってurl-patternが直接サーブレットにマッピングされる。
例えば、
- リクエストのurl-patternがApplication1であれば、@WebServlet("/ Application1 ")の宣言と一致する。
- @WebServlet("/Application1 ")の宣言が直前でされているクラスは、サーブレットAppicationServlet1であるので、このサーブレットが選択される。
バージョン
このドキュメントを書くために使用した各コンポーネントのバージョンを示す。アノテーションは、Servlerのバージョン3.0から採用された技術である。
構成要素 |
バージョン |
Servlet |
3.1. |
Apache Tomcat |
8.5. |
JRE |
1.8 |
アノテーション@WebServlet
アノテーション@WebServletを使用すると、簡単にマッピング情報を含むサーブレットの設定情報を宣言することができる。もし、次のようにURLパターンだけが設定される場合は、要素の名前が設定されていなくてもURLパターンとみなされる。
@WebServlet("/HelloWorld")
もし、二つ以上の要素が宣言される場合は、ひとつの要素がvalueまたはurlPatternでなければならい。
@WebServlet(name="HelloWorldServlet", urlPatterns = {"/HelloWorld", "/Hello"})
アノテーション@WebServletによって設定できる要素を以下に示す。
要素 |
内容 |
name |
サーブレットの名前 |
value |
マッピングのためのURLパターン(urlPatternsが宣言されていれば無効) |
urlPatterns |
マッピングのためのURLパターン |
loadOnStartup |
スタートアップの順序 |
initParams |
サーブレットのための初期化パラメータ |
asyncSupported |
同期サポートの有効性 |
smallIcon |
もし表示するならば、小さなアイコン。 |
largeIcon |
もし表示するならば、大きなアイコン。 |
description |
もし表示するならば、サーブレットの説明。 |
displayName |
もし表示するならば、サーブレットの表示名。 |
シンプルなアノテーションのサンプルプログラム
このサンプルプログラムは、シンプルなアノテーション宣言を使ったものだ。クライアントからのリクエストがサーブレットクラスを呼び出す。そのサーブレットは「Hello World!」を表示するレスポンスを返す。その手順とレスポンスによって表示される画面は実行結果で確認できる。
アノテーションの定義
URLパスよって呼び出されるサーブレットクラスの場所は次の図の通りである。また、URLパスとサーブレットのマッピングはサーブレットにアノテーションとして定義されている。
このコードがアノテーションである。サーブレットにURLパターンがマッピングされている。
@WebServlet("/HelloWorld")//[1]
サンプルプログラム
次のプログラムは、HttpServletクラスを継承して作成されたサーブレットクラスである。リクエストメソッドはGETに対応したdoGet()メソッドのみが実装されている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/HelloWorld")//[1] public class HelloWorld extends HttpServlet {//[]2] protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//[3] response.setContentType("text/html");//[4] PrintWriter out = response.getWriter();//[5] out.println("<html><head></head><body>");//[6] out.println("<p>Simple Application</p>");//[7] out.println("<p>Hello World!</p>");//[8] out.println("</body></html>");//[9] } } |
実行結果
コンテキストルートはServletSimpleAnnotationなので、クライアントからのパスは以下のようになる。
http://localhost:8080/ServletSimpleAnnotation/HelloWorld
次の画面は、このパスをIEのアドレスに入力した結果である。
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] アノテーションの宣言をする。
- [2] HttpServletを継承して、HelloWorldクラスを定義する。
- [3] doGet()メソッドをオーバーライドして定義する。
- [4] Content Typeに「text/html」を設定する。
- [5] HTMLを出力するためのoutオブジェクトを取得する。
- [6]-[9] outオブジェクトに「Simple Application」と「Hello World!」を表示するHTMLコードを出力する。
パッケージに入ったサーブレットのアノテーション
前のセクションのサンプルプログラムは、サーブレットがパッケージ入っていないシンプルな構造だった。今度は、そのサーブレットが次のように「sample」というパッケージに入っている。この場合も、アノテーションによる宣言は、前の「シンプルなアノテーションのサンプルプログラム」と変わらない。
アノテーションの定義
URLパスよって呼び出されるサーブレットクラスの場所は次の図の通りである。また、URLパスとサーブレットのマッピングはサーブレットにアノテーションとして定義されている。
このコードがアノテーションである。次のアノテーションによってサーブレットにURLパターンがマッピングされている。
@WebServlet("/HelloWorld")//[1]
サンプルプログラム
サンプルプログラムのコードは、基本的に「シンプルなアノテーションのサンプルプログラム」と同じである。違いは、最初の行にパッケージの宣言があるだけだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package sample; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/HelloWorld")//[1] public class HelloWorld extends HttpServlet {//[]1] protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//[2] response.setContentType("text/html");//[3] PrintWriter out = response.getWriter();//[4] out.println("<html><head></head><body>");//[5] out.println("<p>Simple Application</p>");//[6] out.println("<p>Hello World!</p>");//[7] out.println("</body></html>");//[8] } } |
実行結果
コンテキストルートはServletPackageAnnotationなので、クライアントからのパスは以下のようになる。
http://localhost:8080/ServletPackageAnnotation/HelloWorld
レスポンス画面は、「シンプルなアノテーションのサンプルプログラム」に同じになる。
サンプルプログラムの説明
プログラムのコードも、パッケージの宣言を除いて「シンプルなアノテーションのサンプルプログラム」に同じである。
@WebInitParamによる初期設定
このサンプルプログラムは、アノテーション@WebServletに@WebInitParamを追加して、サーブレットに初期属性を宣言している。サーブレットは、その初期属性を使って「Hello World!」に続いて都市と国を表示するレスポンスを返す。
アノテーションの定義
URLパスよって呼び出されるサーブレットクラスの場所は次の図の通りである。また、URLパスとサーブレットのマッピングはアノテーションによって宣言されている。
これが、アノテーションの宣言である。サーブレットの初期属性が@WebInitParamのnameとvalueのペアーに設定されている。
1 2 3 4 5 6 7 8 |
@WebServlet(//[1] urlPatterns = {"/HelloWorld"},//[2] initParams =//[3] { @WebInitParam(name = "country", value = "Japan"),//[4] @WebInitParam(name = "city", value = "Tokyo")//[5] } ) |
サンプルプログラム
このプログラムは、HttpServletクラスを継承して作成されたサーブレットクラスである。リクエストメソッドはGETに対応したdoGet()メソッドのみが実装されている。@WebInitParam で宣言された初期属性をgetInitParameter()メソッドで取得して、レスポンスの中で表示している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(//[1] urlPatterns = {"/HelloWorld"},//[2] initParams =//[3] { @WebInitParam(name = "country", value = "Japan"),//[4] @WebInitParam(name = "city", value = "Tokyo")//[5] } ) public class HelloWorld extends HttpServlet {//[]10] protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//[11] String country = getInitParameter("country");//[12] String city = getInitParameter("city");//[13] response.setContentType("text/html");//[14] PrintWriter out = response.getWriter();//[15] out.println("<html><head></head><body>");//[16] out.println("<p>Simple Application</p>");//[17] out.println("<p>Hello World! from " + city + " " + country + ".</p>");//[18] out.println("</body></html>");//[19] } } |
実行結果
コンテキストルートはServletInitParamAnnotationなので、クライアントからのパスは以下のようになる。
http://localhost:8080/ServletInitParamAnnotation/HelloWorld
次の画面は、アノテーションの宣言に対してパスをIEのアドレスに入力した結果である。
サンプルプログラムの説明
それでは簡単にプログラムの解説をしてゆこう。
- [1] アノテーション@WebServletの宣言をする。
- [2] urlPatternsmに「/HelloWorld」を宣言する。
- [3]-[5] initParams の@WebInitParamのnameとvalueのペアー、countryとJapan、cityとTokyoを設定する。
- [10] HttpServletを継承して、HelloWorldクラスを定義する。
- [11] doGet()メソッドをオーバーライドして定義する。
- [12] getInitParameter()メソッドでパラメータ名:countryを取得し、変数countryに代入する。
- [13] getInitParameter()メソッドでパラメータ名:cityを取得し、変数cityに代入する。
- [14] Content Typeに「text/html」を設定する。
- [15] HTMLを出力するためのoutオブジェクトを取得する。
- [16]-[19] outオブジェクトに「Simple Application」と「Hello World! from + (都市名:変数city) + (国名:変数country)」を表示するHTMLコードを出力する。
デフォルトサーブレット
このサンプルプログラムは、デフォルトサーブレットのアノテーション宣言を示すものである。デフォルトサーブレットは、WebコンテナがURLパターンからサーブレットを選択しようとしてサーブレットが見つからないときに呼び出される。
アノテーションの定義
URLパスよって呼び出されるサーブレットクラスの場所は次の図の通りである。また、URLパスとサーブレットのマッピングはサーブレットにアノテーションとして定義されている。
このコードがデフォルトサーブレットのアノテーションである。サーブレットにURLパターンがマッピングされている。サーブレットに紐付けされたURLパターンが文字「/」だけならば、デフォルトサーブレットを定義していることになる。このため、どのURLパターンにも一致しない場合は、このデフォルトサーブレットが選択される。
@WebServlet("/")//[1]
サンプルプログラム
サンプルプログラムのHelloWorldは、「シンプルなアノテーションのサンプルプログラム」と同じである。またDefaultServletも、基本的に「シンプルなアノテーションのサンプルプログラム」と同じである。違いは、クラスの名前と画面の表示だけである。
ここでは、DefaultServletのコードだけを掲載する。HelloWorldは「シンプルなアノテーションのサンプルプログラム」のセクションを参照してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/")//[1] public class DefaultServlet extends HttpServlet {//[2] protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//[3] response.setContentType("text/html");//[4] PrintWriter out = response.getWriter();//[5] out.println("<html><head></head><body>");//[6] out.println("<p>Servlet not found.</p>");//[7] out.println("<p>Default Servlet</p>");//[8] out.println("</body></html>");//[9] } } |
実行結果
コンテキストルートはServletDefaultなので、HelloWorldを呼び出すクライアントからのパスは以下のようになる。
http://localhost:8080/ServletDefault/HelloWorld
次の画面は、このパスをIEのアドレスに入力した結果である。
コンテキストルートはServletDefaultなので、存在しないURLパターンHelloXXXXXを呼び出すクライアントからのパスは以下のようになる。
http://localhost:8080/ServletDefault/HelloXXXXX
次の画面は、このパスをIEのアドレスに入力した結果である。
サンプルプログラムの説明
それでは簡単にデフォルトサーブレットのプログラムの解説をしてゆこう。
- [1] アノテーションの宣言をする。
- [2] HttpServletを継承して、HelloWorldクラスを定義する。
- [3] doGet()メソッドをオーバーライドして定義する。
- [4] Content Typeに「text/html」を設定する。
- [5] HTMLを出力するためのoutオブジェクトを取得する。
- [6]-[9] outオブジェクトに「DefaultServlet」を表示するHTMLコードを出力する。
まとめ
この記事ではJavaで作成したWebアプリケーションの動作について説明した。実際にサンプルプログラムを動作させながら仕組みについて理解を深めよう。