doGet și doPost în Servlets (Programare, Java, Servlets)

dedalo a intrebat.

Am dezvoltat o pagină HTML care trimite informații către un Servlet. În Servlet, folosesc metodele 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");
}

În codul paginii html codul care apelează Servlet-ul este:

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

Când folosesc method = "get" în Servlet, obțin valoarea id-ului și a parolei, însă atunci când folosesc method = "post", id și parola sunt setate la valoarea null. De ce nu obțin valorile în acest caz?

Un alt lucru pe care aș dori să îl știu este cum să folosesc datele generate sau validate de Servlet. De exemplu, dacă Servlet-ul prezentat mai sus autentifică utilizatorul, aș dori să imprim id-ul utilizatorului în pagina mea HTML. Ar trebui să pot trimite șirul de caractere „id” ca răspuns și să pot folosi aceste informații în pagina mea HTML. Este posibil acest lucru?

Comentarii

  • Cum folosiți metoda post în html? –  > Por Igor Artamonov.
  • Și, de asemenea, pentru ce aveți nevoie de o buclă atât de ciudată peste numele parametrilor? –  > Por Igor Artamonov.
  • Ați încercat să eliminați ` enctype=multipart/form-data`? Bănuiesc că asta este problema ta. –  > Por Jack Leow.
  • Asta a fost tot. De ce nu funcționează postarea atunci când este prezentă? Vă mulțumim pentru ajutor! –  > Por dedalo.
5 răspunsuri
BalusC

Introducere

Ar trebui să folosiți doGet() atunci când doriți să interceptați pe cererile HTTP GET. Ar trebui să utilizați doPost() atunci când doriți să interceptați pe cereri HTTP POST. Asta este tot. Nu portați una în cealaltă sau invers (cum ar fi în cazul nefericitului Netbeans autogenerat de Netbeans processRequest() de la Netbeans). Acest lucru nu are niciun sens absolut.

GET

De obicei, cererile HTTP GET sunt idempotente. Adică se obține exact același rezultat de fiecare dată când se execută cererea (fără a se lua în considerare autorizarea/autentificarea și natura sensibilă la timp a paginii -rezultatele căutării, ultimele știri etc.-). Putem vorbi despre o cerere marcabilă. Apăsarea unui link, apăsarea unui marcaj, introducerea URL-ului brut în bara de adrese a browserului etc. toate acestea vor lansa o cerere HTTP GET. Dacă un Servlet ascultă pe URL-ul în cauză, atunci aplicația sa doGet() va fi apelată. Aceasta este utilizată de obicei pentru a preprocesarea o cerere. Adică, pentru a efectua unele activități înainte de a prezenta ieșirea HTML dintr-un JSP, cum ar fi colectarea de date pentru a le afișa într-un tabel.

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

}

Rețineți că fișierul JSP este plasat în mod explicit în fișierul /WEB-INF pentru a preveni ca utilizatorii finali să îl poată accesa direct fără a invoca servlet-ul de preprocesare (și astfel să ajungă să fie confuzi văzând un tabel gol).

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

De asemenea, legăturile de vizualizare/modificare a detaliilor, așa cum se arată în ultima coloană de mai sus, sunt de obicei idempotente.

@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

Cererile HTTP POST nu sunt idempotente. Dacă utilizatorul final a trimis în prealabil un formular POST pe un URL, care nu a efectuat o redirecționare, atunci URL-ul nu este neapărat marcabil. Datele din formularul trimis nu sunt reflectate în URL. Copierea URL-ului într-o nouă fereastră/tab a browserului poate să nu producă neapărat exact același rezultat ca după trimiterea formularului. O astfel de adresă URL nu poate fi adăugată la favorite. În cazul în care un Servlet ascultă pe URL-ul în cauză, atunci aplicația sa doPost() va fi apelat. Acesta este utilizat de obicei pentru a postprocesarea o cerere. Adică, colectarea datelor dintr-un formular HTML trimis și efectuarea unor operațiuni de afaceri cu acestea (conversie, validare, salvare în baza de date etc.). În cele din urmă, de obicei, rezultatul este prezentat ca HTML din pagina JSP transmisă.

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

…care poate fi utilizată în combinație cu această bucată de 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);
        }
    }

}

Vedeți, dacă User este găsit în BD (adică numele de utilizator și parola sunt valide), atunci User va fi pus în domeniul de sesiune (adică „logat”) și servlet-ul va redirecționa către o anumită pagină principală (acest exemplu merge către http://example.com/contextname/home), în caz contrar va seta un mesaj de eroare și va redirecționa cererea către aceeași pagină JSP, astfel încât mesajul să fie afișat de către ${error}.

Dacă este necesar, puteți, de asemenea, să „ascundeți” pagina login.jsp în /WEB-INF/login.jsp astfel încât utilizatorii să o poată accesa doar prin servlet. În acest fel, URL-ul rămâne curat. http://example.com/contextname/login. Tot ce trebuie să faceți este să adăugați un doGet() la servlet astfel:

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

(și actualizați aceeași linie în doPost() în mod corespunzător)

Acestea fiind spuse, nu sunt sigur dacă este vorba doar de joacă și împușcat în întuneric, dar codul pe care l-ați postat nu arată bine (cum ar fi utilizarea de compareTo() în loc de equals() și săpând în numele parametrilor în loc să folosească doar getParameter() și id și password pare să fie declarate ca variabile de instanță servlet – ceea ce NU este threadsafe). Așadar, vă recomand cu tărie să învățați ceva mai multe despre API-ul de bază Java SE, utilizând Tutoriale Oracle (consultați capitolul „Trails Covering the Basics”) și cum să folosiți JSP/Servlets în mod corect folosind aceste tutoriale.

Vedeți și:

  • Pagina noastră wiki Servlets
  • Dezvoltarea web Java EE, de unde încep și de ce competențe am nevoie?
  • Servlet returnează „HTTP Status 404 Resursa solicitată (/servlet) nu este disponibilă”
  • Afișați JDBC ResultSet în HTML în pagina JSP utilizând modelul MVC și DAO

Actualizați: conform actualizării întrebării dvs. (care este destul de majoră, nu ar trebui să eliminați părți din întrebarea dvs. originală, acest lucru ar face ca răspunsurile să fie fără valoare … mai degrabă adăugați informațiile într-un bloc nou) , se pare că setați în mod inutil tipul de codificare al formularului la multipart/form-data. Acest lucru va trimite parametrii cererii într-o compoziție diferită de cea (implicită) application/x-www-form-urlencoded care trimite parametrii de solicitare sub forma unui șir de interogare (de ex. name1=value1&name2=value2&name3=value3). Aveți nevoie doar de multipart/form-data ori de câte ori aveți un <input type="file"> în formular pentru a încărca fișiere care pot fi date fără caractere (date binare). Acest lucru nu este cazul în cazul dvs., așa că eliminați-l și va funcționa conform așteptărilor. Dacă veți avea vreodată nevoie să încărcați fișiere, atunci va trebui să setați tipul de codificare astfel și să analizați singur corpul cererii. În mod normal, folosiți opțiunea Apache Commons FileUpload acolo, dar dacă sunteți deja pe noul API Servlet 3.0, puteți folosi facilitățile integrate începând cu HttpServletRequest#getPart(). Consultați și acest răspuns pentru un exemplu concret: Cum să încărcați fișiere pe server folosind JSP/Servlet?

S. Mayol

Atât GET cât și POST sunt folosite de browser pentru a solicita o singură resursă de la server. Fiecare resursă necesită o cerere GET sau POST separată.

  1. Metoda GET este cea mai frecvent utilizată (și este metoda implicită) de browsere pentru a prelua informații de la servere. Atunci când se utilizează metoda GET, cea de-a treia secțiune a pachetului de cerere, care reprezintă corpul cererii, rămâne goală.

Metoda GET este utilizată în două moduri: Atunci când nu este specificată nicio metodă, adică atunci când dumneavoastră sau browserul solicitați o resursă simplă, cum ar fi o pagină HTML, o imagine etc. Atunci când un formular este trimis și alegeți metoda =GET pe eticheta HTML. Dacă metoda GET este utilizată cu un formular HTML, atunci datele colectate prin intermediul formularului sunt trimise la server prin adăugarea unui „?” la sfârșitul URL-ului și apoi prin adăugarea tuturor perechilor nume=valoare (numele câmpului din formularul html și valoarea introdusă în acel câmp) separate de un „& „Exemplu: GET /sultans/sultans/shop//form1.jsp?name=Sam%20Sultan&iceCream=vanilla HTTP/1.0 optional headeroptional header<< empty line >>>>

Datele formularului name=valoare vor fi stocate într-o variabilă de mediu numită QUERY_STRING. Această variabilă va fi trimisă unui program de procesare (cum ar fi JSP, Java servlet, PHP etc.).

  1. Metoda POST este utilizată atunci când creați un formular HTML, iar metoda de solicitare=POST ca parte a tag-ului. Metoda POST permite clientului să trimită datele formularului către server în secțiunea request body a cererii (așa cum am discutat anterior). Datele sunt codificate și sunt formatate similar cu metoda GET, cu excepția faptului că datele sunt trimise către program prin intrarea standard.

Exemplu:POST POST /sultans/shop//form1.jsp HTTP/1.0 headeropțional header opțional<< empty line >>>> name=Sam%20Sultan&iceCream=vanilie

Atunci când se utilizează metoda post, variabila de mediu QUERY_STRING va fi goală. Avantajele/dezavantajele metodei GET vs. POST

Avantajele metodei GET:Ușor mai rapid Parametrii pot fi introduși printr-un formular sau prin adăugarea lor după URLPagina poate fi marcată cu parametrii săi ca un bookmark

Dezavantaje ale metodei GET:Poate trimite doar date în valoare de 4K. (Nu ar trebui să o utilizați atunci când folosiți un câmp textarea)Parametrii sunt vizibili la sfârșitul URL-ului

Avantajele metodei POST:Parametrii nu sunt vizibili la sfârșitul URL-ului. (Se utilizează pentru date sensibile)Poate trimite serverului mai mult de 4K de date.

Dezavantaje ale metodei POST:Nu poate fi marcat cu datele sale ca un bookmark

Jay Jackson

Implementarea de către containerul servlet a metodei HttpServlet.service() va transmite automat către doGet() sau doPost() după cum este necesar, deci nu ar trebui să fie nevoie să suprascrieți metoda de serviciu.

Tom

S-ar putea ca datele să fie transmise prin get, nu prin post?

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

Dacă faceți <form action="identification" > pentru formularul dvs. html, datele vor fi transmise în mod implicit prin „Get” și, prin urmare, puteți să prindeți acest lucru folosind funcția doGet în codul dvs. de servlet java. În acest fel, datele vor fi transmise sub antetul HTML și, prin urmare, vor fi vizibile în URL atunci când sunt trimise.Pe de altă parte, dacă doriți să transmiteți datele în corpul HTML, atunci UTILIZAȚI Post: <form action="identification" method="post"> și prindeți aceste date în funcția doPost. Astfel, datele vor fi transmise în corpul html și nu în antetul html, iar datele nu vor fi vizibile în URL după trimiterea formularului.

Exemple din html-ul meu:

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

Exemple din codul meu de servlet 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");

.........
.........