1. ホーム
  2. java

[解決済み] サーブレットにおけるdoGetとdoPost

2022-10-31 10:44:02

質問

サーブレットに情報を送信するHTMLページを開発しました。Servletの中で、メソッド doGet()doPost() :

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException  {

     String id = req.getParameter("realname");
     String password = req.getParameter("mypassword");
}

public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {

    String id = req.getParameter("realname");
    String password = req.getParameter("mypassword");
}

サーブレットを呼び出すhtmlページのコードでは

<form action="identification" method="post" enctype="multipart/form-data">
    User Name: <input type="text" name="realname">
    Password: <input type="password" name="mypassword">
    <input type="submit" value="Identification">
</form> 

を使う場合 method = "get" を使うと、id と password の値が得られますが、Servlet で method = "post" を使うと、id と password は null . この場合、なぜ値が取得できないのでしょうか?

もう一つ知りたいのは、Servletによって生成または検証されたデータをどのように使うかということです。例えば、上記のServletがユーザーを認証した場合、HTMLページにユーザーIDを表示したいと思います。文字列 'id' を応答として送信し、この情報を私のHTMLページで使用することができるはずです。それは可能ですか?

どのように解決するのですか?

はじめに

この場合 doGet() で遮蔽したい場合は HTTP GET リクエスト . この場合 doPost() で遮蔽したい場合は HTTP POST リクエスト . 以上です。一方から他方へ、あるいはその逆へ移植しないでください(例えば、Netbeansの不幸な自動生成された processRequest() メソッドのような)。これは全く意味をなしません。

GET

通常、HTTP GET リクエストは べき乗 . つまり、リクエストを実行するたびにまったく同じ結果を得ることができます (認証/オーセンティケーションや、検索結果や最新ニュースなど、ページの時間的な性質は考慮の対象外です)。ブックマーク可能なリクエストについて話すことができます。リンクをクリックする、ブックマークをクリックする、ブラウザのアドレスバーに生のURLを入力する、などなど、すべてHTTP GETリクエストを発生させます。もしサーブレットがその URL をリッスンしていれば、その doGet() メソッドが呼び出されます。これは通常 前処理 リクエストの前処理に使われます。つまり、JSP から HTML 出力を表示する前に、テーブルに表示するためのデータを収集するなど、いくつかのビジネス的なことを行うのです。

@WebServlet("/products")
public class ProductsServlet extends HttpServlet {

    @EJB
    private ProductService productService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        List<Product> products = productService.list();
        request.setAttribute("products", products); // Will be available as ${products} in JSP
        request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
    }

}

JSP ファイルは明示的に /WEB-INF フォルダに置かれることに注意してください。これは、エンドユーザが前処理サーブレットを呼び出さずに直接アクセスできるようにするためです(したがって、空のテーブルを見て混乱してしまうことになります)。

<table>
    <c:forEach items="${products}" var="product">
        <tr>
            <td>${product.name}</td>
            <td><a href="product?id=${product.id}">detail</a></td>
        </tr>
    </c:forEach>
</table>

また、上記の最後のコラムにあるような詳細の表示/編集リンクは通常べき乗です。

@WebServlet("/product")
public class ProductServlet extends HttpServlet {

    @EJB
    private ProductService productService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Product product = productService.find(request.getParameter("id"));
        request.setAttribute("product", product); // Will be available as ${product} in JSP
        request.getRequestDispatcher("/WEB-INF/product.jsp").forward(request, response);
    }

}

<dl>
    <dt>ID</dt>
    <dd>${product.id}</dd>
    <dt>Name</dt>
    <dd>${product.name}</dd>
    <dt>Description</dt>
    <dd>${product.description}</dd>
    <dt>Price</dt>
    <dd>${product.price}</dd>
    <dt>Image</dt>
    <dd><img src="productImage?id=${product.id}" /></dd>
</dl>

POST

HTTP POST リクエストはべき乗ではありません。エンドユーザーがリダイレクトを実行していないURLであらかじめPOSTフォームを送信していた場合、そのURLは必ずしもブックマーク可能とは限りません。送信されたフォームのデータは、URLに反映されません。URLを新しいブラウザのウィンドウやタブにコピーしても、フォーム送信後と全く同じ結果になるとは限りません。このようなURLは、ブックマークには登録できません。もし Servlet が当該 URL を待ち受けているならば、その doPost() が呼び出されます。これは通常 ポストプロセス リクエストに使用されます。つまり、送信されたHTMLフォームからデータを収集し、それを使っていくつかのビジネス上のことを行います(変換、検証、DBへの保存、など)。最終的に通常、結果は転送されたJSPページからのHTMLとして表示されます。

<form action="login" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="login">
    <span class="error">${error}</span>
</form>

...このServletの一部と組み合わせて使用することができます。

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @EJB
    private UserService userService;

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user = userService.find(username, password);

        if (user != null) {
            request.getSession().setAttribute("user", user);
            response.sendRedirect("home");
        }
        else {
            request.setAttribute("error", "Unknown user, please try again");
            request.getRequestDispatcher("/login.jsp").forward(request, response);
        }
    }

}

ほら、もし User が DB で見つかった場合 (すなわち、ユーザ名とパスワードが有効である場合)、その後に User はセッションスコープに置かれ (つまり "logged in") サーブレットはメインページにリダイレクトします (この例では http://example.com/contextname/home にリダイレクトされます)、さもなければエラーメッセージをセットして 同じ JSP ページにリクエストを戻し、そのメッセージが ${error} .

必要であれば、quot;hide" で login.jsp/WEB-INF/login.jsp で囲むことで、ユーザはサーブレットからしかアクセスできないようにします。これによって URL がきれいに保たれます http://example.com/contextname/login . 必要なのは doGet() をこのようにサーブレットに追加するだけです。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}

(の同じ行を更新してください)。 doPost() というように)

とはいえ、ただ単に遊びで闇雲に撮影しているだけなのかどうかはわかりませんが、投稿されたコードはあまり良い印象を受けません(例えば compareTo() の代わりに equals() を使用する代わりに、パラメータ名を掘り下げます。 getParameter()idpassword はサーブレットインスタンス変数として宣言されているように見えますが、これは スレッドセーフ ). というわけで、Java SE の基本的な API について Oracleチュートリアル (の章をご覧ください)、また、JSP/サーブレットを正しく使うには これらのチュートリアル .

こちらもご覧ください。


更新 : あなたの質問の更新に従って (これはかなり重要です。あなたの元の質問の部分を削除してはいけません、これは答えが価値のないものになるでしょう...むしろ) を加える を新しいブロックに追加してください) 、それはあなたが不必要にフォームのエンコードタイプを設定することが判明した multipart/form-data . これは、リクエストパラメータを (デフォルトの) application/x-www-form-urlencoded とは異なり、 リクエストパラメータをクエリ文字列として送ります (例えば name1=value1&name2=value2&name3=value3 ). 必要なのは multipart/form-data が必要なだけです。 <input type="file"> 要素があると、文字以外のデータ (バイナリデータ) である可能性があるファイルをアップロードするためのフォームが表示されます。あなたの場合はそうではないので、これを削除すれば期待通りに動作するようになります。もしファイルをアップロードする必要があるなら、エンコードタイプを設定し、リクエストボディを自分でパースする必要があります。通常、あなたは Apache Commons FileUpload を使いますが、新しいサーブレット 3.0 API を使っている場合は HttpServletRequest#getPart() . 具体的な例として、こちらの回答もご覧ください。 JSP /サーブレットを使用してサーバーにファイルをアップロードする方法は?