第5章: リクエストとレスポンスの処理

HTTPリクエストとレスポンスの理解と処理

この章で学ぶこと
  • HTTPリクエストとレスポンスの基本概念と仕組み
  • requestオブジェクトを使用したデータ取得方法
  • responseオブジェクトを使用した出力制御
  • GETとPOSTメソッドの違いと適切な使い分け
  • フォームデータの処理技術と日本語文字化け対策

5.1 HTTPリクエストとレスポンスの基本

Webアプリケーション開発において、HTTPリクエストとレスポンスの理解は非常に重要です。HTTPは「HyperText Transfer Protocol」の略で、WebブラウザとWebサーバー間でデータをやり取りするためのプロトコル(通信規約)です。

sequenceDiagram participant Browser as Webブラウザ participant Server as Webサーバー participant JSP as JSPページ Browser->>Server: HTTPリクエスト送信 Note over Browser,Server: URL、パラメータ、ヘッダー情報含む Server->>JSP: リクエスト処理依頼 JSP->>JSP: ビジネスロジック実行 JSP->>Server: HTML生成・返却 Server->>Browser: HTTPレスポンス送信 Note over Server,Browser: HTML、ヘッダー、ステータスコード含む

HTTPリクエストの構成要素

  • リクエストライン: HTTPメソッド、URL、HTTPバージョン
  • ヘッダーフィールド: Content-Type、User-Agent、Cookieなど
  • メッセージボディ: POSTメソッドで送信されるデータ

HTTPレスポンスの構成要素

  • ステータスライン: HTTPバージョン、ステータスコード、理由句
  • ヘッダーフィールド: Content-Type、Set-Cookie、Cache-Controlなど
  • メッセージボディ: HTML、JSON、画像データなど

5.2 requestオブジェクトによるデータ取得

JSPでは、requestオブジェクト(HttpServletRequestのインスタンス)を使用して、クライアントから送信されたデータにアクセスできます。このオブジェクトは、JSPの暗黙的オブジェクトの1つです。

主要なrequestオブジェクトのメソッド

メソッド 説明 戻り値
getParameter(String name) 指定したパラメータの値を取得 String
getParameterValues(String name) 同名の複数パラメータを配列で取得 String[]
getParameterNames() 全パラメータ名を取得 Enumeration<String>
getMethod() HTTPメソッドを取得 String
getHeader(String name) 指定したヘッダーの値を取得 String
getRequestURI() リクエストURIを取得 String
実習 5-1: リクエストパラメータの取得

フォームから送信されたデータをJSPで受け取り表示するプログラムを作成します。

手順1: HTMLフォームの作成(form.html)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ユーザー情報入力フォーム</title>
</head>
<body>
    <h2>ユーザー情報入力</h2>
    <form action="processForm.jsp" method="post">
        <p>
            名前: <input type="text" name="username" required>
        </p>
        <p>
            年齢: <input type="number" name="age" min="0" max="150">
        </p>
        <p>
            趣味: 
            <input type="checkbox" name="hobby" value="読書"> 読書
            <input type="checkbox" name="hobby" value="映画"> 映画
            <input type="checkbox" name="hobby" value="スポーツ"> スポーツ
        </p>
        <p>
            <input type="submit" value="送信">
        </p>
    </form>
</body>
</html>
手順2: JSPでのデータ処理(processForm.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>フォーム処理結果</title>
</head>
<body>
    <h2>入力データの確認</h2>
    
    <%
        // 文字エンコーディングの設定(日本語文字化け対策)
        request.setCharacterEncoding("UTF-8");
        
        // パラメータの取得
        String username = request.getParameter("username");
        String ageStr = request.getParameter("age");
        String[] hobbies = request.getParameterValues("hobby");
        
        // リクエスト情報の表示
        String method = request.getMethod();
        String uri = request.getRequestURI();
    %>
    
    <table border="1">
        <tr>
            <th>項目</th>
            <th>値</th>
        </tr>
        <tr>
            <td>名前</td>
            <td><%= username != null ? username : "未入力" %></td>
        </tr>
        <tr>
            <td>年齢</td>
            <td><%= ageStr != null ? ageStr + "歳" : "未入力" %></td>
        </tr>
        <tr>
            <td>趣味</td>
            <td>
                <%
                    if (hobbies != null) {
                        for (String hobby : hobbies) {
                            out.println(hobby + " ");
                        }
                    } else {
                        out.println("選択なし");
                    }
                %>
            </td>
        </tr>
        <tr>
            <td>HTTPメソッド</td>
            <td><%= method %></td>
        </tr>
        <tr>
            <td>リクエストURI</td>
            <td><%= uri %></td>
        </tr>
    </table>
    
    <p><a href="form.html">入力フォームに戻る</a></p>
</body>
</html>
期待される結果

フォームで入力したデータがテーブル形式で表示され、HTTPメソッドとリクエストURIも確認できます。

5.3 GETとPOSTメソッドの理解と使い分け

HTTPには様々なメソッドがありますが、Webアプリケーション開発では主にGETとPOSTメソッドを使用します。それぞれに特徴と適切な使用場面があります。

flowchart TD A[HTTP通信] --> B[GETメソッド] A --> C[POSTメソッド] B --> D["データ取得・表示
(リソースの読み取り)"] B --> E["URLにパラメータ付与
(クエリ文字列)"] B --> F["ブックマーク可能
(冪等性あり)"] C --> G["データ送信・更新
(リソースの変更)"] C --> H["リクエストボディに
パラメータ格納"] C --> I["機密情報送信
(冪等性なし)"]

GETメソッドの特徴

  • 用途: データの取得、検索結果の表示
  • パラメータ: URLのクエリ文字列として送信
  • データサイズ制限: URLの長さ制限(通常2048文字程度)
  • セキュリティ: URLに情報が表示されるため機密情報には不適切
  • キャッシュ: ブラウザやプロキシでキャッシュされる
  • 冪等性: 何度実行しても同じ結果(副作用なし)

POSTメソッドの特徴

  • 用途: データの送信、更新、削除
  • パラメータ: リクエストボディ内に格納
  • データサイズ制限: サーバーの設定により決まる(通常数MB程度)
  • セキュリティ: URLに表示されないため相対的に安全
  • キャッシュ: 通常キャッシュされない
  • 冪等性: 実行のたびに状態が変化する可能性
実習 5-2: GETとPOSTの動作比較

同じデータを GETとPOSTで送信し、動作の違いを確認します。

手順1: 両メソッド対応フォーム(compare.html)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>GET vs POST比較</title>
</head>
<body>
    <h2>GETとPOSTメソッドの比較</h2>
    
    <h3>GETメソッドでの送信</h3>
    <form action="methodCompare.jsp" method="get">
        <p>
            検索キーワード: <input type="text" name="keyword" value="Java">
        </p>
        <p>
            カテゴリ: 
            <select name="category">
                <option value="programming">プログラミング</option>
                <option value="database">データベース</option>
                <option value="web">Webテクノロジー</option>
            </select>
        </p>
        <p>
            <input type="submit" value="GET送信">
        </p>
    </form>
    
    <h3>POSTメソッドでの送信</h3>
    <form action="methodCompare.jsp" method="post">
        <p>
            検索キーワード: <input type="text" name="keyword" value="Java">
        </p>
        <p>
            カテゴリ: 
            <select name="category">
                <option value="programming">プログラミング</option>
                <option value="database">データベース</option>
                <option value="web">Webテクノロジー</option>
            </select>
        </p>
        <p>
            <input type="submit" value="POST送信">
        </p>
    </form>
</body>
</html>
手順2: メソッド比較処理(methodCompare.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>メソッド比較結果</title>
</head>
<body>
    <h2>HTTPメソッド比較結果</h2>
    
    <%
        // 文字エンコーディング設定
        request.setCharacterEncoding("UTF-8");
        
        // リクエスト情報の取得
        String method = request.getMethod();
        String keyword = request.getParameter("keyword");
        String category = request.getParameter("category");
        String queryString = request.getQueryString();
    %>
    
    <table border="1" cellpadding="5">
        <tr>
            <th>項目</th>
            <th>値</th>
            <th>説明</th>
        </tr>
        <tr>
            <td>HTTPメソッド</td>
            <td><%= method %></td>
            <td>使用された通信方式</td>
        </tr>
        <tr>
            <td>キーワード</td>
            <td><%= keyword %></td>
            <td>入力された検索語</td>
        </tr>
        <tr>
            <td>カテゴリ</td>
            <td><%= category %></td>
            <td>選択されたカテゴリ</td>
        </tr>
        <tr>
            <td>クエリ文字列</td>
            <td><%= queryString != null ? queryString : "なし" %></td>
            <td>GETの場合のみURLに付加される</td>
        </tr>
    </table>
    
    <h3>メソッドの特徴</h3>
    <%
        if ("GET".equals(method)) {
    %>
        <div style="background-color: #e7f3ff; padding: 10px; border-left: 4px solid #2196F3;">
            <h4>GETメソッドの特徴</h4>
            <ul>
                <li>URLにパラメータが表示されています(上記のクエリ文字列参照)</li>
                <li>ブックマークや履歴に保存可能</li>
                <li>検索機能など、データ取得に適している</li>
                <li>機密情報の送信には向かない</li>
            </ul>
        </div>
    <%
        } else if ("POST".equals(method)) {
    %>
        <div style="background-color: #fff3e0; padding: 10px; border-left: 4px solid #ff9800;">
            <h4>POSTメソッドの特徴</h4>
            <ul>
                <li>URLにパラメータが表示されません(クエリ文字列がnull)</li>
                <li>大量のデータ送信が可能</li>
                <li>ユーザー登録、データ更新などに適している</li>
                <li>相対的にセキュアな通信</li>
            </ul>
        </div>
    <%
        }
    %>
    
    <p><a href="compare.html">比較フォームに戻る</a></p>
</body>
</html>
期待される結果

GETでは URL にパラメータが表示され、POSTでは表示されない違いを確認できます。

5.4 responseオブジェクトによる出力制御

responseオブジェクト(HttpServletResponseのインスタンス)を使用して、クライアントへのレスポンスを制御できます。

主要なresponseオブジェクトのメソッド

メソッド 説明 用途
setContentType(String type) レスポンスのコンテンツタイプを設定 HTML、JSON、PDFなどの出力形式指定
setCharacterEncoding(String charset) 文字エンコーディングを設定 日本語文字化け対策
sendRedirect(String location) 指定URLへのリダイレクト ページ遷移制御
setHeader(String name, String value) レスポンスヘッダーを設定 キャッシュ制御、セキュリティ設定
addCookie(Cookie cookie) クッキーをレスポンスに追加 ユーザー状態の保存
実習 5-3: レスポンス制御の実践

responseオブジェクトを使用してリダイレクトとヘッダー制御を行います。

手順1: ログインフォーム(login.html)
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ログインフォーム</title>
</head>
<body>
    <h2>ユーザーログイン</h2>
    <form action="authenticate.jsp" method="post">
        <p>
            ユーザー名: <input type="text" name="username" required>
        </p>
        <p>
            パスワード: <input type="password" name="password" required>
        </p>
        <p>
            <input type="submit" value="ログイン">
        </p>
    </form>
</body>
</html>
手順2: 認証処理(authenticate.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" %>
<%
    // 文字エンコーディング設定
    request.setCharacterEncoding("UTF-8");
    
    // パラメータ取得
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    
    // 簡易認証ロジック(実際の開発では暗号化されたパスワードを使用)
    boolean isAuthenticated = false;
    if ("admin".equals(username) && "password123".equals(password)) {
        isAuthenticated = true;
    }
    
    if (isAuthenticated) {
        // 認証成功時の処理
        
        // 1. キャッシュ無効化ヘッダーの設定
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setDateHeader("Expires", 0);
        
        // 2. セキュリティヘッダーの設定
        response.setHeader("X-Content-Type-Options", "nosniff");
        response.setHeader("X-Frame-Options", "DENY");
        
        // 3. 成功ページへリダイレクト
        response.sendRedirect("welcome.jsp?user=" + java.net.URLEncoder.encode(username, "UTF-8"));
        
    } else {
        // 認証失敗時の処理
        
        // 1. コンテンツタイプ設定
        response.setContentType("text/html; charset=UTF-8");
        
        // 2. ステータスコード設定(認証失敗)
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        
        // 3. エラーメッセージ出力
%>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ログインエラー</title>
</head>
<body>
    <h2>ログインに失敗しました</h2>
    <div style="background-color: #ffebee; padding: 15px; border: 1px solid #f44336; border-radius: 5px;">
        <p><strong>エラー:</strong>ユーザー名またはパスワードが正しくありません。</p>
        <p>正しい認証情報を入力してください。</p>
    </div>
    
    <h3>認証情報確認</h3>
    <p>入力されたユーザー名: <%= username %></p>
    <p>HTTPステータス: <%= response.getStatus() %> (Unauthorized)</p>
    
    <p><a href="login.html">ログインページに戻る</a></p>
    
    <div style="background-color: #e3f2fd; padding: 10px; margin-top: 20px;">
        <h4>デモ用認証情報</h4>
        <p>ユーザー名: admin</p>
        <p>パスワード: password123</p>
    </div>
</body>
</html>
<%
    }
%>
手順3: ウェルカムページ(welcome.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ウェルカムページ</title>
</head>
<body>
    <h2>ログイン成功!</h2>
    
    <%
        String user = request.getParameter("user");
        if (user != null) {
    %>
        <div style="background-color: #e8f5e8; padding: 15px; border: 1px solid #4caf50; border-radius: 5px;">
            <h3>ようこそ、<%= user %>さん!</h3>
            <p>正常にログインが完了しました。</p>
        </div>
        
        <h3>セッション情報</h3>
        <ul>
            <li>ユーザー名: <%= user %></li>
            <li>ログイン時刻: <%= new java.util.Date() %></li>
            <li>セッションID: <%= session.getId() %></li>
        </ul>
    <%
        } else {
            // 直接アクセスされた場合
            response.sendRedirect("login.html");
        }
    %>
    
    <p><a href="login.html">ログアウト</a></p>
</body>
</html>
期待される結果
  • 正しい認証情報(admin/password123)でログイン成功
  • 間違った認証情報でエラーページ表示
  • 各種レスポンスヘッダーが適切に設定される

5.5 日本語文字化け対策

日本語を含むWebアプリケーションでは、文字エンコーディングの適切な設定が重要です。UTF-8を標準として統一し、リクエストとレスポンス両方で適切に設定する必要があります。

文字化けの主な原因
  • リクエストとレスポンスで異なる文字エンコーディングを使用
  • ファイル保存時の文字エンコーディングが不適切
  • データベースとの文字エンコーディング不一致
  • サーバー(Tomcat)の設定が不適切

文字エンコーディング設定のベストプラクティス

1. JSPページでの設定
<%-- ページディレクティブで設定 --%>
<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8" %>

<%
    // リクエストの文字エンコーディング設定
    request.setCharacterEncoding("UTF-8");
    
    // レスポンスの文字エンコーディング設定
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
%>
2. HTMLメタタグでの設定
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>日本語対応ページ</title>
</head>
3. フォームでの設定
<form action="process.jsp" method="post" accept-charset="UTF-8">
    <!-- accept-charset属性でエンコーディングを明示 -->
    <input type="text" name="japanese_text">
    <input type="submit" value="送信">
</form>
理解度確認クイズ
  1. HTTPリクエストとレスポンスについて
    HTTPリクエストの主要な構成要素を3つ挙げて、それぞれの役割を説明してください。
  2. GETとPOSTの使い分け
    以下の機能を実装する場合、GETとPOSTのどちらを使用すべきか理由とともに答えてください:
    • 検索機能
    • ユーザー登録
    • 商品詳細表示
    • パスワード変更
  3. requestオブジェクトのメソッド
    複数の値を持つ同名のパラメータ(チェックボックスなど)を取得するには、どのメソッドを使用しますか?また、その戻り値の型は何ですか?
  4. responseオブジェクトの活用
    ログイン成功後にダッシュボードページへリダイレクトするJSPコードを書いてください。
  5. 文字エンコーディング対策
    日本語の文字化けを防ぐために、JSPページで設定すべき3つの項目を挙げてください。

5.6 まとめ

この章では、JSPにおけるHTTPリクエストとレスポンスの処理について詳しく学習しました。

重要なポイント
  • HTTPの基本理解: リクエストとレスポンスの構造と役割
  • requestオブジェクト: パラメータ取得とリクエスト情報の活用
  • responseオブジェクト: レスポンス制御とリダイレクト処理
  • メソッドの使い分け: GETとPOSTの特徴と適切な使用場面
  • 文字エンコーディング: UTF-8による日本語文字化け対策