doGet i doPost w serwletach


105

Opracowałem stronę HTML, która wysyła informacje do serwletu. W serwlecie używam metod doGet()i 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");
}

W kodzie strony html, który wywołuje serwlet, jest:

<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> 

Kiedy używam method = "get"w serwlecie, otrzymuję wartość id i hasło, jednak kiedy używam method = "post", id i hasło są ustawione na null. Dlaczego nie otrzymuję wartości w tym przypadku?

Inną rzeczą, którą chciałbym wiedzieć, jest sposób wykorzystania danych wygenerowanych lub zweryfikowanych przez serwlet. Na przykład, jeśli serwlet pokazany powyżej uwierzytelnia użytkownika, chciałbym wydrukować identyfikator użytkownika na mojej stronie HTML. Powinienem być w stanie wysłać ciąg „id” jako odpowiedź i użyć tych informacji na mojej stronie HTML. Czy to możliwe?


Jak korzystasz z metody post w html?
Igor Artamonov

A także, po co ci tak dziwna pętla nad nazwami parametrów?
Igor Artamonov

1
Czy próbowałeś usunąć „enctype = multipart / form-data”? Podejrzewam, że to twój problem.
Jack Leow,

To było to. Dlaczego post nie działa, gdy jest obecny? Dzięki za pomoc!
dedalo

Odpowiedzi:


197

Wprowadzenie

Powinieneś użyć doGet() gdy chcesz przechwytywać żądania HTTP GET . Powinieneś używać, doPost()gdy chcesz przechwytywać żądania HTTP POST . To wszystko. Nie przenoś jednego do drugiego ani odwrotnie (na przykład w niefortunnej, automatycznie generowanej processRequest()metodzie Netbeans ). To nie ma sensu.

DOSTAĆ

Zwykle żądania HTTP GET są idempotentne . Oznacza to, że otrzymujesz dokładnie ten sam wynik za każdym razem, gdy wykonujesz żądanie (pozostawiając autoryzację / uwierzytelnienie i wrażliwość na czas strony - wyniki wyszukiwania, ostatnie wiadomości itp. - poza rozważeniem). Możemy porozmawiać o żądaniu bukmacherskim. Kliknięcie łącza, kliknięcie zakładki, wprowadzenie surowego adresu URL w pasku adresu przeglądarki itp. Spowoduje uruchomienie żądania HTTP GET. Jeśli serwlet nasłuchuje podanego adresu URL, doGet()zostanie wywołana jego metoda. Zwykle służy do wstępnego przetwarzania żądania. To znaczy robię pewne rzeczy biznesowe przed prezentacją wyjścia HTML ze strony JSP, na przykład zbieranie danych do wyświetlenia w tabeli.

@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>

Również linki do przeglądania / edycji szczegółów, jak pokazano w ostatniej kolumnie powyżej, są zwykle idempotentne.

@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>

POCZTA

Żądania HTTP POST nie są idempotentne. Jeśli użytkownik końcowy przesłał wcześniej formularz POST na adres URL, który nie wykonał przekierowania, to adres URL niekoniecznie musi mieć zakładkę. Przesłane dane formularza nie są odzwierciedlane w adresie URL. Kopiowanie adresu URL do nowego okna / karty przeglądarki niekoniecznie musi dać dokładnie taki sam wynik, jak po przesłaniu formularza. Taki adres URL nie podlega wówczas zakładaniu. Jeśli serwlet nasłuchuje podanego adresu URL, to jegodoPost() zostanie wywołany. Zwykle jest używany do postprocesowania żądania. To znaczy zbieranie danych z przesłanego formularza HTML i robienie z nim pewnych rzeczy biznesowych (konwersja, walidacja, zapisywanie w DB itp.). Ostatecznie zwykle wynik jest przedstawiany jako HTML z przesłanej strony JSP.

<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>

... które mogą być używane w połączeniu z tym fragmentem serwletu:

@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);
        }
    }

}

Widzisz, jeśli User zostanie znaleziony w DB (tj. Nazwa użytkownika i hasło są prawidłowe), to Userzostanie umieszczony w zakresie sesji (tj. "Zalogowany"), a serwlet przekieruje na jakąś stronę główną (ten przykład idzie do http://example.com/contextname/home), w przeciwnym razie ustawi komunikat o błędzie i przekieruje żądanie z powrotem do tej samej strony JSP, aby komunikat został wyświetlony przez ${error}.

W razie potrzeby możesz także „ukryć” login.jspin, /WEB-INF/login.jspaby użytkownicy mieli do niego dostęp tylko przez serwlet. Dzięki temu adres URL jest czysty http://example.com/contextname/login. Wszystko, co musisz zrobić, to dodać plikdoGet() do serwletu w następujący sposób:

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

(i odpowiednio zaktualizuj ten sam wiersz doPost())

To powiedziawszy, nie jestem pewien, czy to jest po prostu grając i filmowania w ciemności, ale kod której pisał nie wygląda dobrze (takich jak używanie compareTo()zamiast equals()i kopanie w parameternames zamiast tylko za pomocą getParameter()a idi passwordwydaje się być zadeklarowane jako zmienne instancji serwletu - które NIE są bezpieczne dla wątków ). Dlatego zdecydowanie polecam, aby dowiedzieć się więcej na temat podstawowego interfejsu API Java SE, korzystając z samouczków Oracle (zobacz rozdział „Szlaki dotyczące podstaw”) i jak prawidłowo korzystać z JSP / Servletów za pomocą tych samouczków .

Zobacz też:


Aktualizacja : zgodnie z aktualizacją twojego pytania (co jest dość duże, nie powinieneś usuwać części swojego pierwotnego pytania, to uczyniłoby odpowiedzi bezwartościowymi ... raczej dodaj informacje w nowym bloku), okazuje się, że jesteś niepotrzebne ustawianie typu kodowania formularza na multipart/form-data. Spowoduje to wysłanie parametrów żądania w innym składzie niż (domyślny)application/x-www-form-urlencoded który wysyła parametry żądania jako ciąg zapytania (np name1=value1&name2=value2&name3=value3.). Potrzebujesz tylko wtedy, multipart/form-datagdy masz<input type="file">element w formularzu do przesłania plików, które mogą być danymi niebędącymi znakami (dane binarne). Tak nie jest w twoim przypadku, więc po prostu go usuń, a będzie działać zgodnie z oczekiwaniami. Jeśli kiedykolwiek będziesz musiał przesłać pliki, będziesz musiał ustawić typ kodowania i samodzielnie przeanalizować treść żądania. Zwykle używasz tam Apache Commons FileUploadale jeśli już korzystasz z nowego interfejsu API Servlet 3.0, możesz po prostu użyć wbudowanych funkcji zaczynających się od HttpServletRequest#getPart(). Zobacz również tę odpowiedź, aby zapoznać się z konkretnym przykładem: Jak przesłać pliki na serwer przy użyciu JSP / Servlet?


2

Zarówno GET, jak i POST są używane przez przeglądarkę do żądania pojedynczego zasobu z serwera. Każdy zasób wymaga osobnego żądania GET lub POST.

  1. Metoda GET jest najczęściej (i jest metodą domyślną) używana przez przeglądarki do pobierania informacji z serwerów. Podczas korzystania z metody GET trzecia sekcja pakietu żądania, która jest treścią żądania, pozostaje pusta.

Metoda GET jest używana na dwa sposoby: Gdy żadna metoda nie jest określona, ​​to znaczy, gdy Ty lub przeglądarka żądacie prostego zasobu, takiego jak strona HTML, obraz, itp. Kiedy formularz jest przesyłany, a Ty wybierasz metodę = POBIERZ znacznik HTML. Jeśli metoda GET jest używana z formularzem HTML, to dane zebrane za pośrednictwem formularza są wysyłane na serwer poprzez dołączenie znaku „?” na końcu adresu URL, a następnie dodanie wszystkich par nazwa = wartość (nazwa pola formularza html i wartość wprowadzona w tym polu) oddzielonych znakiem „&”. Przykład: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 opcjonalny nagłówek opcjonalny nagłówek << pusta linia >>>

Dane z formularza nazwa = wartość będą przechowywane w zmiennej środowiskowej o nazwie QUERY_STRING. Ta zmienna zostanie wysłana do programu przetwarzającego (takiego jak JSP, serwlet Java, PHP itp.)

  1. Metoda POST jest używana podczas tworzenia formularza HTML i żądania method = POST jako część tagu. Metoda POST umożliwia klientowi wysyłanie danych formularza do serwera w sekcji treści żądania (jak omówiono wcześniej). Dane są zakodowane i sformatowane podobnie jak metoda GET, z tą różnicą, że dane są przesyłane do programu przez standardowe wejście.

Przykład: POST /sultans/shop//form1.jsp HTTP / 1.0 opcjonalny nagłówekopcjonalny nagłówek << pusta linia >>> name = Sam% 20Sultan & iceCream = vanilla

Używając metody post, zmienna środowiskowa QUERY_STRING będzie pusta. Zalety / wady GET vs. POST

Zalety metody GET: Nieco szybciej Parametry można wprowadzać za pomocą formularza lub dołączając je po adresie URL Można dodać zakładkę do strony z parametrami

Wady metody GET: może wysyłać tylko dane o wartości 4K. (Nie należy go używać w przypadku korzystania z pola tekstowego) Parametry są widoczne na końcu adresu URL

Zalety metody POST: parametry nie są widoczne na końcu adresu URL. (Użyj dla danych wrażliwych) Może wysłać więcej niż 4K danych do serwera

Wady metody POST: nie można dodać jej danych do zakładek


0

Implementacja metody HttpServlet.service () w kontenerze serwletu będzie automatycznie przekazywać dalej do doGet () lub doPost () w razie potrzeby, więc nie powinno być potrzeby nadpisywania metody usługi.


0

Czy to możliwe, że przesyłasz dane przez get, a nie post?

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

0

Jeśli zrobisz to <form action="identification" >dla swojego formularza html, dane będą domyślnie przekazywane przy użyciu 'Get', a zatem możesz to złapać za pomocą funkcji doGet w kodzie serwletu Java. W ten sposób dane będą przekazywane pod nagłówkiem HTML, a tym samym będą widoczne w adresie URL po przesłaniu. Z drugiej strony, jeśli chcesz przekazać dane w treści HTML, użyj Post: <form action="identification" method="post">i przechwyć te dane w funkcji doPost. Tak było, dane będą przekazywane pod treść html, a nie nagłówek html, a po przesłaniu formularza nie zobaczysz danych w adresie URL.

Przykłady z mojego html:

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

Przykłady z mojego kodu serwletu 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");

.........
.........
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.