解説 · セクション 4
HttpServlet を継承する
Servlet を作るときの定型 (extends + @Override doGet/doPost) を身近な例で。
身近に置き換えると
Servlet(サーブレット)をレストランの「受付係(ウェイター)」だと想像してみてください。お客さん(ブラウザ)がお店にやってきて、「ハンバーグ定食をお願い」と注文(リクエスト)をします。受付係は注文票を受け取り、厨房に伝えて、出来上がった料理(レスポンス)をお客さんのテーブルに運びます。
Javaでこの受付係をゼロから育てるのは大変なので、すでに基本的な接客マニュアルを身につけているベテラン受付係(HttpServlet)の能力を受け継ぎ(継承し)ます。そして、「注文の受け取り方」や「料理の出し方」だけを自分のお店専用に書き換える(オーバーライドする)ことで、簡単にWebアプリケーションを作ることができます。
3 行でまとめると
- Webプログラムを作るには、便利な基本クラスである
HttpServletをextends(継承)する。 - アクセス方法に合わせて
doGetやdoPostを@Overrideして、自分のお店のルールを書く。 req.getParameterでお客さんの注文内容を受け取り、res.getWriterでお返事を書き込む。
図で見ると
classDiagram
class HttpServlet {
+doGet(req, res)
+doPost(req, res)
}
class MyServlet {
+doGet(req, res)
+doPost(req, res)
}
HttpServlet <|-- MyServlet
class HttpServletRequest {
+getParameter(name)
}
class HttpServletResponse {
+getWriter()
}
MyServlet ..> HttpServletRequest : 注文を受け取る
MyServlet ..> HttpServletResponse : 返事を書き込む
HttpServlet を継承(矢印)することで、Webサーバーとやり取りする複雑な仕組みをそのまま引き継ぎます。私たちは doGet や doPost の中身を上書きするだけで済みます。
順を追って理解する
1. HttpServlet を継承する
Web上で動くプログラムを作るための第一歩は、クラス宣言に extends HttpServlet をつけることです。これにより、ただのJavaクラスが「Webサーバー上でリクエストを受け取れるServletクラス」に生まれ変わります。
2. doGet / doPost をオーバーライドする
お客さんからのアクセス方法には、主に「GET(ページを見るだけ)」と「POST(フォームからデータを送る)」があります。これに合わせて doGet または doPost メソッドを上書きします。このとき、引数の型は必ず HttpServletRequest と HttpServletResponse に固定されています。
また、通信エラーなどに備えて、メソッドには throws ServletException, IOException という例外を宣言する必要があります。
3. 安全装置として @Override を書く
メソッドを上書きする際は、必ずメソッドの直前に @Override を書きましょう。これは必須ではありませんが、「親クラスのメソッドを正しく上書きしているか」をJavaがチェックしてくれる強力な安全装置になります。
4. リクエストからデータを取り出す
お客さんが入力したデータ(検索キーワードや名前など)は、1つ目の引数である HttpServletRequest(よく req と略されます)に入っています。req.getParameter("キー名") を使うと、そのデータを文字列として取り出すことができます。
5. レスポンスに結果を書き込む
処理が終わったら、お客さんの画面(ブラウザ)に結果を返します。2つ目の引数である HttpServletResponse(よく res と略されます)から res.getWriter() を呼ぶと、文字を書き込むためのペン(出力ストリーム)がもらえます。これを使ってHTMLなどの文章を出力します。
応用ではこう書く
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;
// URLが "/hello" のときにこのServletが動く
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
// GETリクエストが来たときの処理を上書き
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// 1. お客さんからのデータ(パラメータ)を受け取る
// 例: /hello?name=田中
String userName = req.getParameter("name");
if (userName == null) {
userName = "ゲスト";
}
// 2. お客さんに返す文字のルール(文字化け対策)を設定
res.setContentType("text/html; charset=UTF-8");
// 3. お客さんに返事(HTML)を書き込む
PrintWriter out = res.getWriter();
out.println("<html><body>");
out.println("<h1>こんにちは、" + userName + "さん!</h1>");
out.println("</body></html>");
}
}
実際の開発では、Servletの中で直接HTMLをたくさん書くことは少なくなり、画面作りは「JSP(JavaServer Pages)」という別の仕組みに任せるようになります(MVCモデル)。しかし、リクエストを受け取ってレスポンスを返すという基本の流れは全く同じです。
よくある誤解
誤解: @Override は書かなくても動くから不要?
正しくは: 動くこともありますが、必ず書くべきです。例えば doget のように小文字でタイポ(打ち間違い)をした場合、@Override がないとJavaは「新しい別のメソッドを作ったんだな」と勘違いし、エラーを出さずに処理を無視してしまいます。@Override を書いておけば、タイポした瞬間にコンパイルエラーとして間違いを教えてくれます。
誤解: 引数の名前は必ず req と res にしなければならない?
正しくは: 変数名は自由です。request や response と書いても全く問題ありません。しかし、変数の「型」である HttpServletRequest と HttpServletResponse は絶対に固定です。この型が少しでも違うと、正しくオーバーライドできません。
つまずいたら
このトピックで詰まったら基礎復習へ: 章 3 クラスの継承