web-dev-qa-db-ja.com

サーブレットでのdoGetおよびdoPost

情報をサーブレットに送信するHTMLページを開発しました。サーブレットでは、メソッド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とパスワードの値が取得されますが、method = "post"を使用すると、IDとパスワードはnullに設定されます。この場合、なぜ値を取得しないのですか?

もう1つ知りたいのは、サーブレットによって生成または検証されたデータの使用方法です。たとえば、上記のサーブレットがユーザーを認証する場合、HTMLページにユーザーIDを印刷したいと思います。文字列「id」を応答として送信し、この情報をHTMLページで使用できるはずです。出来ますか?

103
dedalo

前書き

HTTP GETリクエスト でインターセプトする場合は、 doGet() を使用する必要があります。 HTTP POSTリクエスト でインターセプトする場合は、 doPost() を使用する必要があります。それで全部です。 (Netbeansの不幸な自動生成processRequest()メソッドなどで)一方を他方に移植したり、その逆を移植したりしないでください。これはまったく意味がありません。

GET

通常、HTTP GETリクエストは idempotent です。つまりリクエストを実行するたびにまったく同じ結果が得られます(許可/認証、および時間の影響を受けやすいページの性質(検索結果、最新ニュースなど)は考慮されません)。ブックマーク可能なリクエストについて話すことができます。リンクをクリックする、ブックマークをクリックする、ブラウザのアドレスバーに生のURLを入力するなど、すべてがHTTP GETリクエストを発行します。サーブレットが問題のURLでリッスンしている場合、そのdoGet()メソッドが呼び出されます。通常、リクエストのpreprocessに使用されます。つまり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);
    }

}
<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リクエストはべき等ではありません。エンドユーザーがリダイレクトを実行していないPOSTフォームをURLに事前に送信した場合、URLは必ずしもブックマーク可能とは限りません。送信されたフォームデータはURLに反映されません。 URLをコピーして新しいブラウザウィンドウ/タブに貼り付けても、フォーム送信後と同じ結果になるとは限りません。そのようなURLはブックマークできません。サーブレットが問題のURLをリッスンしている場合、そのdoPost()が呼び出されます。通常、リクエストのpostprocessに使用されます。つまり送信された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>

...このサーブレットと組み合わせて使用​​できます:

@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がセッションスコープに置かれ(つまり、「ログイン」)、サーブレットはメインページにリダイレクトします(この例はhttp://example.com/contextname/homeに移動します) )、エラーメッセージを設定し、同じJSPページにリクエストを転送して、${error}によってメッセージが表示されるようにします。

必要に応じて、login.jsp/WEB-INF/login.jspを「非表示」にして、ユーザーがサーブレットからのみアクセスできるようにすることもできます。これにより、http://example.com/contextname/loginのURLがクリーンになります。必要なことは、次のようにサーブレットにdoGet()を追加することだけです。

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

(それに応じてdoPost()の同じ行を更新します)

とはいえ、単に遊んで暗闇で撮影しているのかどうかはわかりませんが、投稿したコードは見栄えがよくありません(たとえば、compareTo()の代わりにequals()を使用し、getParameter()idおよびpasswordは、サーブレットインスタンス変数として宣言されているようですが、これは threadsafe ではありません。したがって、 Oracle tutorials (「基本をカバーするトレイル」の章を参照)とJSP /サーブレットを正しい方法で使用する方法を使用して、基本的なJava SE APIについてもう少し学ぶことを強くお勧めします- これらのチュートリアル

こちらもご覧ください:


Update:質問の更新に従って(これはかなり重要です。元の質問の一部を削除しないでください。これは回答を価値のないものにします。むしろadd新しいブロックの情報)、フォームのエンコードタイプを不必要に multipart/form-data に設定していることがわかります。これは、リクエストパラメータをクエリ文字列として送信する(デフォルト)application/x-www-form-urlencoded(例:name1=value1&name2=value2&name3=value3)とは異なる構成でリクエストパラメータを送信します。フォームにmultipart/form-data要素がある場合は、非文字データ(バイナリデータ)である可能性のあるファイルをアップロードするために、<input type="file">のみが必要です。これはあなたの場合には当てはまらないので、削除するだけで期待通りに動作します。ファイルをアップロードする必要がある場合は、エンコードタイプを設定し、リクエスト本文を自分で解析する必要があります。通常は Apache Commons FileUpload を使用しますが、既に新しいServlet 3.0 APIを使用している場合は、 HttpServletRequest#getPart() で始まる組み込み機能を使用できます。具体的な例については、この回答も参照してください。 JSP/Servletを使用してファイルをサーバーにアップロードする方法

188
BalusC

ブラウザは、GETとPOSTの両方を使用して、サーバーから単一のリソースを要求します。各リソースには、個別のGETまたはPOST要求が必要です。

  1. GETメソッドは、サーバーから情報を取得するためにブラウザーで使用される最も一般的な(そしてデフォルトのメソッドです)。 GETメソッドを使用する場合、リクエスト本体であるリクエストパケットの3番目のセクションは空のままです。

GETメソッドは、2つの方法のいずれかで使用されます。メソッドが指定されていない場合、つまり、ユーザーまたはブラウザーがHTMLページや画像などの単純なリソースを要求している場合。フォームが送信され、メソッドを選択する場合= HTMLタグで取得。 GETメソッドがHTMLフォームで使用される場合、フォームを介して収集されたデータは、「?」を追加することによりサーバーに送信されます。 URLの最後に、「&」で区切られたすべてのname = valueペア(htmlフォームフィールドの名前とそのフィールドに入力された値)を追加します。例:GET /sultans/shop//form1.jsp?name= Sam%20Sultan&iceCream = Vanilla HTTP/1.0オプションヘッダーオプションヘッダー<<空行>>>

Name = valueフォームデータは、QUERY_STRINGと呼ばれる環境変数に保存されます。この変数は、処理プログラム(JSP、Javaサーブレット、PHPなど)に送信されます。

  1. POSTメソッドは、HTMLフォームを作成し、タグの一部としてmethod = POSTを要求するときに使用されます。 POSTメソッドを使用すると、クライアントはリクエストのリクエスト本文セクションでサーバーにフォームデータを送信できます(前述のとおり)。データはエンコードされ、GETメソッドと同様にフォーマットされますが、データは標準入力を介してプログラムに送信されます。

例:POST /sultans/shop//form1.jsp HTTP/1.0 optional headeroptional header << empty line >>> name = Sam%20Sultan&iceCream = Vanilla

Postメソッドを使用する場合、QUERY_STRING環境変数は空になります。 GETとPOSTの利点/欠点

GETメソッドの利点:フォームを介して、またはURLページをパラメーターでブックマークした後に追加することで、パラメーターを少し速く入力できます

GETメソッドの欠点:4K相当のデータしか送信できません。 (textareaフィールドを使用する場合は使用しないでください)パラメーターはURLの最後に表示されます

POSTメソッドの利点:パラメーターはURLの最後に表示されません。 (機密データに使用)4K以上のデータをサーバーに送信できます

POSTメソッドの短所:データでブックマークすることはできません

2
S. Mayol

ポストではなく、getを介してデータを渡している可能性がありますか?

<form method="get" ..>
..
</form>
0
Tom

サーブレットコンテナのHttpServlet.service()メソッドの実装は、必要に応じてdoGet()またはdoPost()に自動的に転送されるため、サービスメソッドをオーバーライドする必要はありません。

0
Jay Jackson

Htmlフォームに対して<form action="identification" >を実行すると、デフォルトで「Get」を使用してデータが渡されるため、JavaサーブレットコードでdoGet関数を使用してこれをキャッチできます。この方法では、データはHTMLヘッダーの下に渡されるため、送信時にURLに表示されます。一方、HTMLボディでデータを渡したい場合は、Post:<form action="identification" method="post">を使用して、このデータをdoPost関数でキャッチします。これは、データがhtmlヘッダーではなくhtmlボディの下に渡されるため、フォームを送信した後、URLにデータが表示されないことです。

私のhtmlからの例:

<body>  
<form action="StartProcessUrl" method="post">
.....
.....

私のJavaサーブレットコードの例:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        PrintWriter out = response.getWriter();
         String surname = request.getParameter("txtSurname");
         String firstname = request.getParameter("txtForename");
         String rqNo = request.getParameter("txtRQ6");
         String nhsNo = request.getParameter("txtNHSNo");

         String attachment1 = request.getParameter("base64textarea1");
         String attachment2 = request.getParameter("base64textarea2");

.........
.........
0