doGet et doPost dans les servlets

105

J'ai développé une page HTML qui envoie des informations à un servlet. Dans le servlet, j'utilise les méthodes doGet()et 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");
}

Dans le code de page html qui appelle le servlet est:

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

Lorsque j'utilise method = "get"dans le servlet, j'obtiens la valeur de l'identifiant et du mot de passe, mais lors de l'utilisation method = "post", l'identifiant et le mot de passe sont définis sur null. Pourquoi n'obtiens-je pas les valeurs dans ce cas?

Une autre chose que j'aimerais savoir est comment utiliser les données générées ou validées par le servlet. Par exemple, si le servlet illustré ci-dessus authentifie l'utilisateur, j'aimerais imprimer l'ID utilisateur dans ma page HTML. Je devrais pouvoir envoyer la chaîne «id» comme réponse et utiliser cette information dans ma page HTML. C'est possible?

dedalo
la source
Comment utilisez-vous la méthode de publication en html?
Igor Artamonov
Et aussi, pourquoi avez-vous besoin d'une boucle si étrange sur les noms de paramètres?
Igor Artamonov
1
Avez-vous essayé de supprimer `enctype = multipart / form-data`? Je soupçonne que c'est votre problème.
Jack Leow
C'était ça. Pourquoi la publication ne fonctionne-t-elle pas quand elle est présente? Merci de votre aide!
dedalo

Réponses:

197

introduction

Vous devez utiliser doGet()lorsque vous souhaitez intercepter des requêtes HTTP GET . Vous devez utiliser doPost()lorsque vous souhaitez intercepter des requêtes HTTP POST . C'est tout. Ne portez pas l'un sur l'autre ou vice versa (comme dans la malheureuse processRequest()méthode auto-générée de Netbeans ). Cela n'a aucun sens.

AVOIR

Habituellement, les requêtes HTTP GET sont idempotentes . C'est-à-dire que vous obtenez exactement le même résultat à chaque fois que vous exécutez la requête (en laissant l'autorisation / authentification et la nature sensible du temps de la page — résultats de la recherche, dernières nouvelles, etc. — hors de considération). Nous pouvons parler d'une demande pouvant être mise en signet. Cliquer sur un lien, cliquer sur un signet, saisir une URL brute dans la barre d'adresse du navigateur, etc. déclencheront tous une requête HTTP GET. Si un servlet écoute sur l'URL en question, sa doGet()méthode sera appelée. Il est généralement utilisé pour prétraiter une demande. C'est-à-dire faire des affaires avant de présenter la sortie HTML d'une JSP, comme la collecte de données à afficher dans un tableau.

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

De plus, afficher / modifier les liens détaillés comme indiqué dans la dernière colonne ci-dessus sont généralement idempotents.

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

PUBLIER

Les requêtes HTTP POST ne sont pas idempotentes. Si l'utilisateur final a préalablement soumis un formulaire POST sur une URL, qui n'a pas effectué de redirection, alors l'URL ne peut pas nécessairement être mise en signet. Les données de formulaire soumises ne sont pas reflétées dans l'URL. Copypaster l'URL dans une nouvelle fenêtre / onglet de navigateur ne donnera pas nécessairement exactement le même résultat qu'après l'envoi du formulaire. Une telle URL ne peut alors pas être mise en signet. Si un servlet écoute sur l'URL en question, alors doPost()il sera appelé. Il est généralement utilisé pour post - traiter une demande. C'est-à-dire collecter des données à partir d'un formulaire HTML soumis et faire des affaires avec lui (conversion, validation, sauvegarde dans DB, etc.). Enfin, le résultat est généralement présenté au format HTML à partir de la page JSP transférée.

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

... qui peut être utilisé en combinaison avec ce morceau 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);
        }
    }

}

Vous voyez, si le Userest trouvé dans DB (c'est-à-dire que le nom d'utilisateur et le mot de passe sont valides), alors le Usersera mis dans la portée de la session (c'est-à-dire "connecté") et le servlet sera redirigé vers une page principale (cet exemple va à http://example.com/contextname/home), sinon il définira un message d'erreur et transmettra la demande à la même page JSP afin que le message soit affiché par ${error}.

Vous pouvez si nécessaire également "masquer" l' login.jspentrée /WEB-INF/login.jsppour que les utilisateurs ne puissent y accéder que par le servlet. Cela maintient l'URL propre http://example.com/contextname/login. Tout ce que vous avez à faire est d'ajouter un doGet()au servlet comme ceci:

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

(et mettre à jour la même ligne en doPost()conséquence)

Cela dit, je ne sais pas s'il s'agit simplement de jouer et de filmer dans le noir, mais le code que vous avez posté n'a pas l'air bien (comme utiliser à la compareTo()place equals()et creuser dans les noms de paramètres au lieu d'utiliser simplement getParameter()et le idet passwordsemble être déclarée comme des variables d'instance de servlet - ce qui n'est PAS threadsafe ). Je vous recommande donc fortement d'en apprendre un peu plus sur l'API Java SE de base en utilisant les tutoriels Oracle (consultez le chapitre "Trails Covering the Basics") et comment utiliser JSP / Servlets correctement en utilisant ces tutoriels .

Voir également:


Mise à jour : selon la mise à jour de votre question (ce qui est assez important, vous ne devriez pas supprimer des parties de votre question d'origine, cela rendrait les réponses sans valeur ... ajoutez plutôt les informations dans un nouveau bloc), il s'avère que vous êtes définir inutilement le type de codage du formulaire sur multipart/form-data. Cela enverra les paramètres de demande dans une composition différente de celle (par défaut) application/x-www-form-urlencodedqui envoie les paramètres de demande sous forme de chaîne de requête (par exemple name1=value1&name2=value2&name3=value3). Vous n'avez besoin multipart/form-dataque lorsque vous avez un<input type="file">élément dans le formulaire pour télécharger des fichiers qui peuvent être des données sans caractère (données binaires). Ce n'est pas le cas dans votre cas, alors supprimez-le simplement et cela fonctionnera comme prévu. Si jamais vous avez besoin de télécharger des fichiers, vous devrez définir le type d'encodage et analyser vous-même le corps de la requête. Habituellement, vous utilisez Apache Commons FileUpload là pour, mais si vous utilisez déjà la nouvelle API Servlet 3.0, vous pouvez simplement utiliser les fonctionnalités intégrées en commençant par HttpServletRequest#getPart(). Voir aussi cette réponse pour un exemple concret: Comment télécharger des fichiers sur le serveur en utilisant JSP / Servlet?

BalusC
la source
2

GET et POST sont tous deux utilisés par le navigateur pour demander une seule ressource au serveur. Chaque ressource nécessite une requête GET ou POST distincte.

  1. La méthode GET est la plus couramment (et est la méthode par défaut) utilisée par les navigateurs pour récupérer des informations sur les serveurs. Lors de l'utilisation de la méthode GET, la 3e section du paquet de requête, qui est le corps de la requête, reste vide.

La méthode GET est utilisée de deux manières: lorsqu'aucune méthode n'est spécifiée, c'est-à-dire lorsque vous ou le navigateur demandez une ressource simple telle qu'une page HTML, une image, etc. Lorsqu'un formulaire est soumis et que vous choisissez la méthode = GET sur la balise HTML. Si la méthode GET est utilisée avec un formulaire HTML, les données collectées via le formulaire sont envoyées au serveur en ajoutant un "?" à la fin de l'URL, puis en ajoutant toutes les paires nom = valeur (nom du champ de formulaire html et valeur saisie dans ce champ) séparées par un "&" Exemple: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 en-tête optionnel en-tête optionnel << ligne vide >>>

Les données du formulaire nom = valeur seront stockées dans une variable d'environnement appelée QUERY_STRING. Cette variable sera envoyée à un programme de traitement (tel que JSP, servlet Java, PHP etc.)

  1. La méthode POST est utilisée lorsque vous créez un formulaire HTML et que la méthode request = POST fait partie de la balise. La méthode POST permet au client d'envoyer des données de formulaire au serveur dans la section corps de la requête de la requête (comme indiqué précédemment). Les données sont codées et sont formatées de la même manière que la méthode GET, sauf que les données sont envoyées au programme via l'entrée standard.

Exemple: POST /sultans/shop//form1.jsp HTTP / 1.0 en-tête facultatif en-tête optionnel << ligne vide >>> nom = Sam% 20Sultan & iceCream = vanilla

Lorsque vous utilisez la méthode de publication, la variable d'environnement QUERY_STRING sera vide. Avantages / inconvénients de GET vs POST

Avantages de la méthode GET: des paramètres légèrement plus rapides peuvent être saisis via un formulaire ou en les ajoutant après que la page URL puisse être mise en signet avec ses paramètres

Inconvénients de la méthode GET: ne peut envoyer que 4K de données. (Vous ne devez pas l'utiliser lors de l'utilisation d'un champ textarea) Les paramètres sont visibles à la fin de l'URL

Avantages de la méthode POST: Les paramètres ne sont pas visibles à la fin de l'URL. (À utiliser pour les données sensibles) Peut envoyer plus de 4K de données au serveur

Inconvénients de la méthode POST: ne peut pas être mis en signet avec ses données

S. Mayol
la source
0

L'implémentation de la méthode HttpServlet.service () dans le conteneur de servlet sera automatiquement transmise à doGet () ou doPost () si nécessaire, vous ne devriez donc pas avoir besoin de remplacer la méthode de service.

Jay Jackson
la source
0

Se pourrait-il que vous transmettiez les données via get, pas par courrier?

<form method="get" ..>
..
</form>
À M
la source
0

Si vous le faites <form action="identification" >pour votre formulaire html, les données seront transmises en utilisant 'Get' par défaut et vous pouvez donc l'attraper en utilisant la fonction doGet dans votre code de servlet java. De cette façon, les données seront transmises sous l'en-tête HTML et seront donc visibles dans l'URL une fois soumises. D'un autre côté, si vous voulez passer des données dans un corps HTML, alors USE Post: <form action="identification" method="post">et récupérez ces données dans la fonction doPost. En effet, les données seront passées sous le corps html et non dans l'en-tête html, et vous ne verrez pas les données dans l'URL après avoir soumis le formulaire.

Exemples de mon html:

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

Exemples de mon code 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");

.........
.........
Uzair Zaman Sheikh
la source