doGet y doPost en Servlets

105

Desarrollé una página HTML que envía información a un Servlet. En el Servlet, estoy usando los métodos doGet()y 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");
}

En el código de la página html que llama al servlet es:

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

Cuando uso method = "get"en el Servlet, obtengo el valor de id y contraseña, sin embargo, cuando uso method = "post", id y contraseña están configurados en null. ¿Por qué no obtengo los valores en este caso?

Otra cosa que me gustaría saber es cómo usar los datos generados o validados por el Servlet. Por ejemplo, si el Servlet que se muestra arriba autentica al usuario, me gustaría imprimir la identificación del usuario en mi página HTML. Debería poder enviar la cadena 'id' como respuesta y usar esta información en mi página HTML. ¿Es posible?

Dedalo
fuente
¿Cómo estás usando el método de publicación en html?
Igor Artamonov
Y también, ¿para qué necesita un bucle tan extraño sobre los nombres de los parámetros?
Igor Artamonov
1
¿Ha intentado eliminar `enctype = multipart / form-data`? Sospecho que ese es tu problema.
Jack Leow
Eso fue todo. ¿Por qué no publica el trabajo cuando está presente? ¡Gracias por tu ayuda!
dedalo

Respuestas:

197

Introducción

Debe utilizarlo doGet()cuando desee interceptar solicitudes HTTP GET . Debe utilizarlo doPost()cuando desee interceptar solicitudes HTTP POST . Eso es todo. No transfiera el uno al otro o viceversa (como en el desafortunado processRequest()método generado automáticamente por Netbeans ). Esto no tiene mucho sentido.

OBTENER

Por lo general, las solicitudes HTTP GET son idempotentes . Es decir, obtiene exactamente el mismo resultado cada vez que ejecuta la solicitud (dejando la autorización / autenticación y la naturaleza sensible al tiempo de la página —resultados de búsqueda, últimas noticias, etc.— fuera de consideración). Podemos hablar sobre una solicitud que se pueda marcar como favorito. Al hacer clic en un enlace, hacer clic en un marcador, ingresar una URL sin procesar en la barra de direcciones del navegador, etc., se activará una solicitud HTTP GET. Si un Servlet está escuchando en la URL en cuestión, se doGet()llamará a su método. Por lo general, se usa para preprocesar una solicitud. Es decir, hacer algunas cosas comerciales antes de presentar la salida HTML de una JSP, como recopilar datos para mostrarlos en una tabla.

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

Además, los enlaces para ver / editar detalles como se muestra en la última columna de arriba suelen ser idempotentes.

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

ENVIAR

Las solicitudes HTTP POST no son idempotentes. Si el usuario final ha enviado un formulario POST en una URL de antemano, que no ha realizado un redireccionamiento, entonces la URL no es necesariamente marcable. Los datos del formulario enviado no se reflejan en la URL. Copiar la URL en una nueva ventana / pestaña del navegador puede no producir necesariamente exactamente el mismo resultado que después de enviar el formulario. Entonces, dicha URL no se puede marcar como favorito. Si un Servlet está escuchando en la URL en cuestión, doPost()se llamará. Suele utilizarse para posprocesar una solicitud. Es decir, recopilar datos de un formulario HTML enviado y hacer algunas cosas comerciales con él (conversión, validación, guardado en DB, etcétera). Por último, normalmente el resultado se presenta como HTML desde la página JSP reenviada.

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

... que se puede utilizar en combinación con esta pieza 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);
        }
    }

}

Verá, si Userse encuentra en la base de datos (es decir, el nombre de usuario y la contraseña son válidos), entonces Userse colocará en el alcance de la sesión (es decir, "inició sesión") y el servlet se redirigirá a alguna página principal (este ejemplo va a http://example.com/contextname/home), de lo contrario establecerá un mensaje de error y reenviará la solicitud a la misma página JSP para que el mensaje sea mostrado por ${error}.

Usted puede si es necesario también "ocultar" el login.jspde /WEB-INF/login.jspmodo que los usuarios sólo pueden acceder a él por el servlet. Esto mantiene limpia la URL http://example.com/contextname/login. Todo lo que necesita hacer es agregar un doGet()al servlet de esta manera:

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

(y actualice la misma línea en doPost()consecuencia)

Dicho esto, no estoy seguro si es sólo jugar alrededor y disparar en la oscuridad, pero el código que usted envió no se ve bien (como el uso compareTo()en lugar de equals()y cavar en los parameternames en lugar de usar getParameter()y el idy passwordparece declararse como variables de instancia de servlet, que NO es seguro para subprocesos ). Por lo tanto, recomendaría encarecidamente aprender un poco más sobre la API básica de Java SE utilizando los tutoriales de Oracle (consulte el capítulo "Senderos que cubren los conceptos básicos") y cómo usar JSP / Servlets de la manera correcta usando esos tutoriales .

Ver también:


Actualización : según la actualización de su pregunta (que es bastante importante, no debe eliminar partes de su pregunta original, esto haría que las respuestas no valieran nada ... en lugar de agregar la información en un nuevo bloque), resulta que está establecer innecesariamente el tipo de codificación del formulario en multipart/form-data. Esto enviará los parámetros de la solicitud en una composición diferente a la (predeterminada) application/x-www-form-urlencodedque envía los parámetros de la solicitud como una cadena de consulta (por ejemplo name1=value1&name2=value2&name3=value3). Solo necesitas multipart/form-datasiempre que tengas un<input type="file">elemento en el formulario para cargar archivos que pueden ser datos sin caracteres (datos binarios). Este no es el caso en su caso, así que simplemente elimínelo y funcionará como se esperaba. Si alguna vez necesita cargar archivos, tendrá que configurar el tipo de codificación y analizar el cuerpo de la solicitud usted mismo. Por lo general, usa Apache Commons FileUpload allí, pero si ya está en la nueva API de Servlet 3.0, entonces puede usar las instalaciones integradas comenzando con HttpServletRequest#getPart(). Consulte también esta respuesta para ver un ejemplo concreto: ¿Cómo cargar archivos al servidor usando JSP / Servlet?

BalusC
fuente
2

El navegador utiliza tanto GET como POST para solicitar un único recurso del servidor. Cada recurso requiere una solicitud GET o POST separada.

  1. El método GET es el que más comúnmente utilizan los navegadores (y es el método predeterminado) para recuperar información de los servidores. Cuando se usa el método GET, la tercera sección del paquete de solicitud, que es el cuerpo de la solicitud, permanece vacía.

El método GET se utiliza de dos formas: cuando no se especifica ningún método, es decir, cuando usted o el navegador solicita un recurso simple, como una página HTML, una imagen, etc. Cuando se envía un formulario y usted elige el método = GET en la etiqueta HTML. Si el método GET se usa con un formulario HTML, los datos recopilados a través del formulario se envían al servidor agregando un "?" al final de la URL y luego agregar todos los pares nombre = valor (nombre del campo del formulario html y valor ingresado en ese campo) separados por un "&" Ejemplo: GET /sultans/shop//form1.jsp?name= Sam% 20Sultan & iceCream = vanilla HTTP / 1.0 encabezado opcional encabezado opcional << línea vacía >>>

Los datos del formulario nombre = valor se almacenarán en una variable de entorno llamada QUERY_STRING. Esta variable se enviará a un programa de procesamiento (como JSP, Java servlet, PHP, etc.)

  1. El método POST se utiliza cuando crea un formulario HTML y el método de solicitud = POST como parte de la etiqueta. El método POST permite al cliente enviar datos del formulario al servidor en la sección del cuerpo de la solicitud (como se explicó anteriormente). Los datos están codificados y formateados de manera similar al método GET, excepto que los datos se envían al programa a través de la entrada estándar.

Ejemplo: POST /sultans/shop//form1.jsp HTTP / 1.0 encabezado opcional encabezado opcional << línea vacía >>> name = Sam% 20Sultan & iceCream = vanilla

Al usar el método de publicación, la variable de entorno QUERY_STRING estará vacía. Ventajas / desventajas de GET frente a POST

Ventajas del método GET: Se pueden ingresar parámetros un poco más rápido a través de un formulario o agregándolos después de que la página URL se pueda marcar con sus parámetros

Desventajas del método GET: solo se pueden enviar datos en 4K. (No debe usarlo cuando use un campo de área de texto) Los parámetros son visibles al final de la URL

Ventajas del método POST: los parámetros no son visibles al final de la URL. (Usar para datos confidenciales) Puede enviar más de 4K de datos al servidor

Desventajas del método POST: no se puede marcar con sus datos

S. Mayol
fuente
0

La implementación del contenedor de servlets del método HttpServlet.service () se reenviará automáticamente a doGet () o doPost () según sea necesario, por lo que no debería necesitar anular el método de servicio.

Jay Jackson
fuente
0

¿Podría ser que esté pasando los datos a través de get, no post?

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

Si lo hace <form action="identification" >para su formulario html, los datos se pasarán usando 'Get' de forma predeterminada y, por lo tanto, puede detectar esto usando la función doGet en su código de servlet java. De esta manera, los datos se pasarán bajo el encabezado HTML y, por lo tanto, serán visibles en la URL cuando se envíen. Por otro lado, si desea pasar datos en el cuerpo HTML, <form action="identification" method="post">utilice Publicar: y capture estos datos en la función doPost. Esto fue, los datos se pasarán bajo el cuerpo html y no bajo el encabezado html, y no verá los datos en la URL después de enviar el formulario.

Ejemplos de mi html:

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

Ejemplos de mi código 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
fuente