【Sevlet/JSP】「doGet/doPostメソッド」と「リクエスト/レスポンスオブジェクト」徹底解説

2025-08-04

はじめに:HTTPメソッドとServletの関係

前回の「Servletの基本構造」に続き、今回はServletの中核機能であるdoGet/doPostメソッドと、重要なHttpServletRequest/HttpServletResponseオブジェクトについて詳しく解説します。これらの概念を理解することで、JSPとServletを効果的に連携させ、より強力なWebアプリケーションを構築できるようになります。

http-servlet

第1章 doGetとdoPostメソッドの詳細

1.1 doGetメソッドの役割と実装

doGetメソッドはHTTP GETリクエストを処理するために使用されます。主に以下のような場面で利用されます:

  • データの取得
  • ページの表示
  • 検索操作
  • パラメータ付きのリンク

基本的なdoGetの実装例:

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

    // クエリパラメータの取得
    String name = request.getParameter("name");
    String age = request.getParameter("age");

    // コンテンツタイプ設定
    response.setContentType("text/html; charset=UTF-8");

    // HTML出力
    PrintWriter out = response.getWriter();
    out.println("");
    out.println("GET処理サンプル");
    out.println("");
    out.println("

受信したデータ

"); out.println("

名前: " + name + "

"); out.println("

年齢: " + age + "

"); out.println(""); out.println(""); }

1.2 doPostメソッドの役割と実装

doPostメソッドはHTTP POSTリクエストを処理するために使用されます。主に以下のような場面で利用されます:

  • データの送信
  • フォームの処理
  • 機密情報の送信
  • データの更新・作成

基本的なdoPostの実装例:

protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

    // フォームデータの取得(POSTの場合はボディに含まれる)
    String username = request.getParameter("username");
    String password = request.getParameter("password");

    // 認証処理(簡易版)
    if ("admin".equals(username) && "secret".equals(password)) {
        // 認証成功 - セッションにユーザー情報を保存
        HttpSession session = request.getSession();
        session.setAttribute("user", username);

        // ウェルカムページへリダイレクト
        response.sendRedirect("welcome.jsp");
    } else {
        // 認証失敗 - エラーメッセージを設定してログインページへフォワード
        request.setAttribute("error", "無効なユーザー名またはパスワード");
        request.getRequestDispatcher("login.jsp").forward(request, response);
    }
}

1.3 doGetとdoPostの使い分け基準

基準GETPOST
データの可視性URLに表示されるリクエストボディに含まれる
データサイズ制限あり(URL長の制約)制限ほぼなし
キャッシュ可能通常不可
ブックマーク可能不可
冪等性冪等(何度実行しても同じ結果)非冪等(状態が変わる可能性)
使用例ページ表示、検索データ送信、更新処理

適切な使い分けの例:

@WebServlet("/user")
public class UserServlet extends HttpServlet {

    // ユーザー情報表示(GET)
    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response)
            throws ServletException, IOException {
        // ユーザー情報取得処理
        request.getRequestDispatcher("/userView.jsp").forward(request, response);
    }

    // ユーザー情報更新(POST)
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response)
            throws ServletException, IOException {
        // ユーザー情報更新処理
        updateUser(request);
        response.sendRedirect("user?updated=true");
    }
}

第2章 HttpServletRequestオブジェクトの詳細

2.1 リクエスト情報の取得

HttpServletRequestオブジェクトから取得できる主な情報:

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

    // 基本情報
    String method = request.getMethod(); // "GET", "POST"など
    String uri = request.getRequestURI(); // "/app/user"
    String protocol = request.getProtocol(); // "HTTP/1.1"

    // クライアント情報
    String remoteAddr = request.getRemoteAddr(); // クライアントIP
    String userAgent = request.getHeader("User-Agent"); // ブラウザ情報

    // パラメータ取得
    String param = request.getParameter("param"); // 単一値
    String[] multiParams = request.getParameterValues("multi"); // 複数値

    // 属性情報
    Object attribute = request.getAttribute("attr");

    // セッション取得
    HttpSession session = request.getSession(); // 既存または新規セッション
    HttpSession existingSession = request.getSession(false); // 既存のみ

    // その他
    Cookie[] cookies = request.getCookies(); // クッキー配列
    Locale locale = request.getLocale(); // クライアントのロケール
}

2.2 リクエストパラメータの処理

マルチパラメータの処理例(チェックボックスなど):

protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

    // 選択された趣味を取得(複数選択可能)
    String[] hobbies = request.getParameterValues("hobby");

    if (hobbies != null && hobbies.length > 0) {
        request.setAttribute("selectedHobbies", Arrays.asList(hobbies));
    } else {
        request.setAttribute("message", "趣味が選択されていません");
    }

    request.getRequestDispatcher("/result.jsp").forward(request, response);
}

パラメータのバリデーション例:

protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

    String email = request.getParameter("email");
    String password = request.getParameter("password");

    // バリデーション
    List errors = new ArrayList<>();

    if (email == null || email.isEmpty()) {
        errors.add("メールアドレスが入力されていません");
    } else if (!email.matches(".+@.+\\..+")) {
        errors.add("メールアドレスの形式が不正です");
    }

    if (password == null || password.isEmpty()) {
        errors.add("パスワードが入力されていません");
    } else if (password.length() < 8) {
        errors.add("パスワードは8文字以上必要です");
    }

    if (!errors.isEmpty()) {
        request.setAttribute("errors", errors);
        request.getRequestDispatcher("/register.jsp").forward(request, response);
        return;
    }

    // バリデーション通過後の処理
    // ...
}

2.3 リクエスト属性の活用

リクエスト属性は、ServletからJSPにデータを渡す際に特に有用です:

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

    // ビジネスロジックからデータ取得
    List products = productService.getFeaturedProducts();

    // リクエスト属性に設定
    request.setAttribute("products", products);
    request.setAttribute("currentDate", new Date());

    // JSPにフォワード
    request.getRequestDispatcher("/featuredProducts.jsp").forward(request, response);
}

JSP側での属性利用:

<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>注目商品</title>
</head>
<body>
    <h1>注目商品一覧 (${currentDate})</h1>
    <ul>
        <c:forEach items="${products}" var="product">
            <li>${product.name} - ${product.price}円</li>
        </c:forEach>
    </ul>
</body>
</html>

第3章 HttpServletResponseオブジェクトの詳細

3.1 レスポンスの構成要素

HttpServletResponseオブジェクトで制御できる主なレスポンス要素:

  1. ステータスコード
  2. ヘッダー
  3. ボディコンテンツ
  4. クッキー
  5. エンコーディング

3.2 レスポンスの基本設定

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

    // ステータスコード設定
    response.setStatus(HttpServletResponse.SC_OK); // 200

    // コンテンツタイプ設定(必須)
    response.setContentType("text/html; charset=UTF-8");

    // キャッシュ制御
    response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);

    // エンコーディング設定
    response.setCharacterEncoding("UTF-8");

    // レスポンス書き込み
    PrintWriter out = response.getWriter();
    out.println("

レスポンスの基本設定

"); out.println("

現在時刻: " + new Date() + "

"); }

3.3 リダイレクトの実装

リダイレクトは新しいURLへの転送を行います:

protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

    // フォーム処理
    String action = request.getParameter("action");

    if ("login".equals(action)) {
        // ログイン処理後、ホームページへリダイレクト
        response.sendRedirect(request.getContextPath() + "/home.jsp");
    } else if ("logout".equals(action)) {
        // セッション無効化後、ログインページへリダイレクト
        request.getSession().invalidate();
        response.sendRedirect(request.getContextPath() + "/login.jsp");
    } else {
        // 不正なアクションの場合、エラーページへリダイレクト
        response.sendRedirect(request.getContextPath() + "/error.jsp");
    }
}

3.4 ファイルダウンロードの実装

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

    // ダウンロードするファイルのパス
    String filePath = "/path/to/file.pdf";
    File downloadFile = new File(filePath);

    // コンテンツタイプ設定
    response.setContentType("application/pdf");

    // コンテンツ長設定
    response.setContentLength((int) downloadFile.length());

    // ヘッダー設定(ダウンロードダイアログ表示)
    String headerKey = "Content-Disposition";
    String headerValue = String.format("attachment; filename=\"%s\"", 
                                      downloadFile.getName());
    response.setHeader(headerKey, headerValue);

    // ファイルを出力ストリームに書き込み
    try (InputStream in = new FileInputStream(downloadFile);
         OutputStream out = response.getOutputStream()) {

        byte[] buffer = new byte[4096];
        int bytesRead;

        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
    }
}

第4章 実践的な応用例

4.1 REST風APIの実装

@WebServlet("/api/products/*")
public class ProductApiServlet extends HttpServlet {

    private ProductService productService = new ProductService();

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

        response.setContentType("application/json; charset=UTF-8");
        PrintWriter out = response.getWriter();

        try {
            String pathInfo = request.getPathInfo();

            if (pathInfo == null || pathInfo.equals("/")) {
                // 全商品取得 /api/products/
                List products = productService.getAllProducts();
                out.print(new Gson().toJson(products));
            } else {
                // 特定商品取得 /api/products/{id}
                String[] parts = pathInfo.split("/");
                if (parts.length == 2) {
                    int id = Integer.parseInt(parts[1]);
                    Product product = productService.getProductById(id);
                    if (product != null) {
                        out.print(new Gson().toJson(product));
                    } else {
                        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                        out.print("{\"error\":\"Product not found\"}");
                    }
                }
            }
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            out.print("{\"error\":\"" + e.getMessage() + "\"}");
        }
    }

    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("application/json; charset=UTF-8");
        PrintWriter out = response.getWriter();

        try {
            // JSONボディの解析
            StringBuilder sb = new StringBuilder();
            String line;
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            Product product = new Gson().fromJson(sb.toString(), Product.class);
            productService.addProduct(product);

            response.setStatus(HttpServletResponse.SC_CREATED);
            out.print(new Gson().toJson(product));
        } catch (Exception e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            out.print("{\"error\":\"" + e.getMessage() + "\"}");
        }
    }
}

4.2 エラーハンドリングのベストプラクティス

カスタムエラーページの設定:

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

    try {
        // 何らかの処理
        processRequest(request);

    } catch (NumberFormatException e) {
        // クライアントエラー (400 Bad Request)
        request.setAttribute("error", "無効な数値形式です");
        request.setAttribute("statusCode", HttpServletResponse.SC_BAD_REQUEST);
        request.getRequestDispatcher("/error.jsp").forward(request, response);

    } catch (UnauthorizedException e) {
        // 認証エラー (401 Unauthorized)
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "認証が必要です");

    } catch (Exception e) {
        // サーバーエラー (500 Internal Server Error)
        log.error("処理中にエラーが発生しました", e);
        request.setAttribute("error", e.getMessage());
        request.setAttribute("statusCode", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        request.getRequestDispatcher("/error.jsp").forward(request, response);
    }
}

web.xmlでのエラーページ設定:

<error-page>
    <error-code>404</error-code>
    <location>/error/404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/error/500.jsp</location>
</error-page>
<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/error/general.jsp</location>
</error-page>

第5章 パフォーマンスとセキュリティ

5.1 レスポンスの最適化

コンテンツ圧縮の実装:

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

    // クライアントがgzipをサポートしているか確認
    String acceptEncoding = request.getHeader("Accept-Encoding");
    boolean supportsGzip = acceptEncoding != null && 
                          acceptEncoding.contains("gzip");

    // 圧縮対応のコンテンツタイプ
    String contentType = "text/html; charset=UTF-8";

    if (supportsGzip) {
        response.setHeader("Content-Encoding", "gzip");
        response.setContentType(contentType);

        try (GZIPOutputStream gzipOut = new GZIPOutputStream(response.getOutputStream());
             PrintWriter writer = new PrintWriter(new OutputStreamWriter(gzipOut, "UTF-8"))) {

            // コンテンツ生成
            generateContent(writer);

        } catch (IOException e) {
            // エラーハンドリング
        }
    } else {
        // 非圧縮レスポンス
        response.setContentType(contentType);
        PrintWriter out = response.getWriter();
        generateContent(out);
    }
}

5.2 セキュリティ対策

CSRF対策の実装:

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

    // CSRFトークン生成
    String csrfToken = UUID.randomUUID().toString();
    request.getSession().setAttribute("csrfToken", csrfToken);

    // JSPにフォワード
    request.setAttribute("csrfToken", csrfToken);
    request.getRequestDispatcher("/form.jsp").forward(request, response);
}

protected void doPost(HttpServletRequest request, 
                      HttpServletResponse response)
        throws ServletException, IOException {

    // CSRFトークンチェック
    String sessionToken = (String) request.getSession().getAttribute("csrfToken");
    String requestToken = request.getParameter("csrfToken");

    if (sessionToken == null || !sessionToken.equals(requestToken)) {
        response.sendError(HttpServletResponse.SC_FORBIDDEN, "無効なCSRFトークン");
        return;
    }

    // 正規の処理
    // ...
}

XSS対策の実装:

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

    // ユーザー入力取得
    String userInput = request.getParameter("input");

    // XSS対策(HTMLエスケープ)
    String safeInput = escapeHtml(userInput);

    // JSPに渡す
    request.setAttribute("safeInput", safeInput);
    request.getRequestDispatcher("/display.jsp").forward(request, response);
}

private String escapeHtml(String input) {
    if (input == null) {
        return "";
    }
    return input.replace("&", "&")
               .replace("<", "<")
               .replace(">", ">")
               .replace("\"", """)
               .replace("'", "'");
}

まとめ:doGet/doPostとリクエスト/レスポンスの重要性

本記事では、Servletの中核機能であるdoGet/doPostメソッドとHttpServletRequest/HttpServletResponseオブジェクトについて詳細に解説しました。これらの概念を理解することで、以下のようなことができるようになります:

  1. HTTPリクエストを効果的に処理できる
  2. 適切なHTTPメソッドを選択して設計できる
  3. クライアントとの安全で効率的な通信を実現できる
  4. JSPとServletを効果的に連携させられる
  5. パフォーマンスとセキュリティを考慮したアプリケーションを構築できる

Servletのこれらの基本機能をマスターすることは、JSPを用いた堅牢なWebアプリケーション開発の基盤となります。次回は、さらに高度なServletの機能について解説する予定です。