doGet e doPost in Servlets


105

Ho sviluppato una pagina HTML che invia informazioni a un servlet. Nel Servlet, sto usando i metodi doGet()e 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");
}

Nel codice della pagina html che chiama il Servlet è:

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

Quando lo uso method = "get"nel servlet, ottengo il valore di id e password, tuttavia quando uso method = "post", id e password sono impostati su null. Perché non ottengo i valori in questo caso?

Un'altra cosa che vorrei sapere è come utilizzare i dati generati o convalidati dal servlet. Ad esempio, se il servlet mostrato sopra autentica l'utente, vorrei stampare l'ID utente nella mia pagina HTML. Dovrei essere in grado di inviare la stringa "id" come risposta e utilizzare queste informazioni nella mia pagina HTML. È possibile?


Come stai usando il metodo post su html?
Igor Artamonov

E inoltre, cosa ti serve per un ciclo così strano sui nomi dei parametri?
Igor Artamonov

1
Hai provato a rimuovere `enctype = multipart / form-data`? Sospetto che sia il tuo problema.
Jack Leow

Questo è tutto. Perché la pubblicazione non funziona quando è presente? Grazie per l'aiuto!
dedalo

Risposte:


197

introduzione

Dovresti usare doGet()quando vuoi intercettare le richieste HTTP GET . Da utilizzare doPost()quando si desidera intercettare le richieste HTTP POST . È tutto. Non portare l'uno all'altro o viceversa (come nel malaugurato processRequest()metodo di generazione automatica di Netbeans ). Questo non ha assolutamente senso.

OTTENERE

Di solito, le richieste HTTP GET sono idempotenti . Vale a dire che si ottiene esattamente lo stesso risultato ogni volta che si esegue la richiesta (lasciando l'autorizzazione / autenticazione e la natura time-sensitive della pagina - risultati di ricerca, ultime notizie, ecc. - al di fuori della considerazione). Possiamo parlare di una richiesta segnalibro. Facendo clic su un collegamento, facendo clic su un segnalibro, inserendo un URL non elaborato nella barra degli indirizzi del browser, eccetera, verrà attivata una richiesta HTTP GET. Se un servlet è in ascolto sull'URL in questione, doGet()verrà chiamato il suo metodo. Di solito viene utilizzato per preelaborare una richiesta. Cioè fare alcune cose di lavoro prima di presentare l'output HTML da un JSP, come la raccolta di dati per la visualizzazione in una tabella.

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

Anche visualizzare / modificare i collegamenti ai dettagli come mostrato nell'ultima colonna sopra sono generalmente idempotenti.

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

INVIARE

Le richieste HTTP POST non sono idempotenti. Se l'utente finale ha inviato in anticipo un modulo POST su un URL, che non ha eseguito un reindirizzamento, l'URL non è necessariamente segnalibro. I dati del modulo inviato non si riflettono nell'URL. Copiare l'URL in una nuova finestra / scheda del browser potrebbe non produrre necessariamente lo stesso risultato dopo l'invio del modulo. Un tale URL non è quindi segnalibro. Se un servlet è in ascolto sull'URL in questione, doPost()verrà chiamato. Di solito viene utilizzato per postelaborare una richiesta. Cioè raccogliere dati da un modulo HTML inviato e fare alcune cose di lavoro con esso (conversione, convalida, salvataggio in DB, eccetera). Infine, di solito il risultato viene presentato come HTML dalla pagina JSP inoltrata.

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

... che può essere utilizzato in combinazione con questo pezzo di 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);
        }
    }

}

Vedi, se Usersi trova nel DB (cioè nome utente e password sono validi), allora Usersarà messo nell'ambito della sessione (cioè "loggato") e il servlet reindirizzerà a qualche pagina principale (questo esempio va a http://example.com/contextname/home), altrimenti imposterà un messaggio di errore e inoltrerà la richiesta alla stessa pagina JSP in modo che il messaggio venga visualizzato da ${error}.

Se necessario si può anche "nascondere" la in login.jspin /WEB-INF/login.jspmodo che gli utenti possano accedervi solo dal servlet. Ciò mantiene pulito l'URL http://example.com/contextname/login. Tutto quello che devi fare è aggiungere un doGet()al servlet in questo modo:

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

(e aggiorna la stessa riga di doPost()conseguenza)

Detto questo, non sono sicuro che stia solo giocando e sparando al buio, ma il codice che hai pubblicato non sembra buono (come usare compareTo()invece di equals()e scavare nei nomi dei parametri invece di usare getParameter()e il ide passwordsembra essere dichiarate come variabili di istanza servlet - che NON è threadsafe ). Quindi consiglio vivamente di imparare un po 'di più sull'API Java SE di base utilizzando i tutorial Oracle (controllare il capitolo "Trails Covering the Basics") e su come utilizzare JSP / Servlet nel modo corretto utilizzando questi tutorial .

Guarda anche:


Aggiornamento : come per l'aggiornamento della tua domanda (che è piuttosto importante, non dovresti rimuovere parti della tua domanda originale, questo renderebbe le risposte inutili .. piuttosto aggiungi le informazioni in un nuovo blocco), si scopre che sei impostando inutilmente il tipo di codifica del form su multipart/form-data. Questo invierà i parametri della richiesta in una composizione diversa da quella (predefinita) application/x-www-form-urlencodedche invia i parametri della richiesta come stringa di query (ad esempio name1=value1&name2=value2&name3=value3). Hai bisogno solo multipart/form-dataogni volta che hai un file<input type="file">elemento nel modulo per caricare file che possono essere dati non di caratteri (dati binari). Questo non è il tuo caso, quindi rimuovilo e funzionerà come previsto. Se hai bisogno di caricare file, dovrai impostare il tipo di codifica così e analizzare tu stesso il corpo della richiesta. Di solito usi Apache Commons FileUpload lì per, ma se sei già su una nuova API Servlet 3.0, puoi semplicemente usare le funzionalità integrate a partire da HttpServletRequest#getPart(). Vedi anche questa risposta per un esempio concreto: come caricare file sul server usando JSP / Servlet?


2

Sia GET che POST vengono utilizzati dal browser per richiedere una singola risorsa dal server. Ogni risorsa richiede una richiesta GET o POST separata.

  1. Il metodo GET è più comunemente (ed è il metodo predefinito) utilizzato dai browser per recuperare le informazioni dai server. Quando si utilizza il metodo GET, la terza sezione del pacchetto di richiesta, che è il corpo della richiesta, rimane vuota.

Il metodo GET viene utilizzato in due modi: quando non viene specificato alcun metodo, ovvero quando tu o il browser richiedete una risorsa semplice come una pagina HTML, un'immagine, ecc. Quando viene inviato un modulo e scegliete il metodo = OTTIENI il tag HTML. Se il metodo GET viene utilizzato con un modulo HTML, i dati raccolti tramite il modulo vengono inviati al server aggiungendo un "?" alla fine dell'URL, quindi aggiungendo tutte le coppie nome = valore (nome del campo modulo html e valore immesso in quel campo) separate da una "&" Esempio: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 intestazione opzionale intestazione opzionale << riga vuota >>>

I dati del modulo nome = valore verranno archiviati in una variabile di ambiente denominata QUERY_STRING. Questa variabile verrà inviata a un programma di elaborazione (come JSP, Java servlet, PHP ecc.)

  1. Il metodo POST viene utilizzato quando crei un modulo HTML e richiedi method = POST come parte del tag. Il metodo POST consente al client di inviare i dati del modulo al server nella sezione del corpo della richiesta (come discusso in precedenza). I dati sono codificati e formattati in modo simile al metodo GET, tranne per il fatto che i dati vengono inviati al programma tramite lo standard input.

Esempio: POST /sultans/shop//form1.jsp HTTP / 1.0 intestazione facoltativa facoltativa << riga vuota >>> nome = Sam% 20Sultan & iceCream = vanilla

Quando si utilizza il metodo post, la variabile d'ambiente QUERY_STRING sarà vuota. Vantaggi / svantaggi di GET rispetto a POST

Vantaggi del metodo GET: i parametri leggermente più veloci possono essere inseriti tramite un modulo o aggiungendoli dopo che la pagina URL può essere contrassegnata con i suoi parametri

Svantaggi del metodo GET: può inviare solo dati di valore 4K. (Non dovresti usarlo quando usi un campo textarea) I parametri sono visibili alla fine dell'URL

Vantaggi del metodo POST: i parametri non sono visibili alla fine dell'URL. (Utilizzare per dati sensibili) Può inviare più di 4K di dati al server

Svantaggi del metodo POST: non può essere aggiunto ai segnalibri con i suoi dati


0

L'implementazione del metodo HttpServlet.service () del contenitore servlet verrà inoltrata automaticamente a doGet () o doPost () secondo necessità, quindi non dovrebbe essere necessario sovrascrivere il metodo di servizio.


0

Potrebbe essere che stai passando i dati tramite get, non post?

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

0

Se lo fai <form action="identification" >per il tuo modulo html, i dati verranno passati usando 'Get' per impostazione predefinita e quindi puoi catturarlo usando la funzione doGet nel tuo codice servlet java. In questo modo i dati verranno passati sotto l'intestazione HTML e quindi saranno visibili nell'URL una volta inviati. D'altra parte, se vuoi passare i dati nel corpo HTML, allora USA Post: <form action="identification" method="post">e cattura questi dati nella funzione doPost. Cioè, i dati verranno passati sotto il corpo html e non nell'intestazione html, e non vedrai i dati nell'URL dopo aver inviato il modulo.

Esempi dal mio html:

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

Esempi dal mio codice 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");

.........
.........
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.