Servlets y JSP

Si alguna vez has usado un motor de b�squeda Web, visitado un tienda de libros on-line, etc., probablemente habr�s encontrado URLs de b�squeda divertidas como http://host/path?user=Marty+Hall&origin=bwi&dest=lax. La parte posterior a la interrogaci�n (user=Marty+Hall&origin=bwi&dest=lax) es conocida como datos de formulario, y es la forma m�s com�n de obtener datos desde una p�gina Web para un programa del lado del servidor. Puede a�adirse al final de la URL despu�s de la interrogaci�n (como arriba) para peticiones GET o enviada al servidor en una l�nea separada, para peticiones POST.

Extraer la informaci�n necesaria desde estos datos de formulario es tradicionalmente una de las partes m�s tediosas de la programaci�n CGI

Primero de todo, tenemos que leer los datos de una forma para las peticiones GET (en CGI tradicional, esto se hace mediante QUERY_STRING), y de otra forma para peticiones POST (normalmente leyendo la entrada est�ndard).

Segundo, tenemos que separar las parejas de los ampersands, luego separar los nombres de los par�metros (a la izquierda de los signos igual) del valor del par�metro (a la derecha de los signos igual).

Tercero, tenemos que decodificar los valores. Los valores alfanum�ricos no cambian, pero los espacios son convertidos a signos m�s y otros caracteres se convierten como %XX donde XX es el valor ASCII (o ISO Latin-1) del car�cter, en hexadecimal. Por ejemplo, si alguien introduce un valor de "~hall, ~gates, y ~mcnealy" en un campo de texto con el nombre "users" en un formulario HTML, los datos ser�an enviados como "users=%7Ehall%2C+%7Egates%2C+and+%7Emcnealy".

Finalmente, la cuarta raz�n que hace que el an�lisis de los datos de formulario sea tedioso es que los valores pueden ser omitidos (por ejemplo, param1=val1&param2=&param3=val3) y un par�metro puede tener m�s de un valor y que el mismo par�metro puede aparecer m�s de una vez (por ejemplo: param1=val1&param2=val2&param1=val3).

Una de las mejores caracter�sticas de los servlets Java es que todos estos an�lisis de formularios son manejados autom�ticamente. Simplemente llamamos al m�todo getParameter de HttpServletRequest, y suministramos el nombre del par�metro como un argumento. Observa que los nombres de par�metros son sensibles a la may�sculas. Hacemos esto exactamente igual que cuando los datos son enviados mediante GET o como si los enviaramos mediante POST. El valor de retorno es un String correspondiente al valor uudecode de la primera ocurrencia del par�metro. Se devuelve un String vac�o si el par�metro existe pero no tiene valor, y se devuelve null si no existe dicho par�metro. Si el par�metro pudiera tener m�s de un valor, como en el ejemplo anterior, deber�amos llamar a getParameterValues en vez de a getParameter. Este devuelve un array de strings. Finalmente, aunque en aplicaciones reales nuestros servlets probablemente tengan un conjunto espec�fico de nombres de par�metros por los que buscar. Usamos getParameterNames para esto, que devuelve una Enumeration, cada entrada puede ser forzada a String y usada en una llamada a getParameter.

.�Ejemplo: Leer Tres Par�metros

Aqu� hay un sencillo ejemplo que lee tres par�metros llamados param1, param2, y param3, listando sus valores en una lista marcada. Observamos que, aunque tenemos que especificar selecciones de respuesta (content type, status line, otras cabeceras HTTP) antes de empezar a generar el contenido, no es necesario que leamos los par�metros de petici�n en un orden particular.

Tambi�n observamos que podemos crear f�cilmente servlets que puedan manejar datos GET y POST, simplemente haciendo que su m�todo doPost llame a doGet o sobreescribiendo service (que llama a doGet, doPost, doHead, etc.). Esta es una buena pr�ctica est�ndard, ya que requiere muy poco trabajo extra y permite flexibilidad en el lado del cliente. Si hemos usado la aproximaci�n CGI tradicional cuando leemos los datos POST mediante la entrada est�ndard. Deber�amos observar que hay una forma similar con los Servlets llamando primero a getReader o getInputStream sobre HttpServletRequest. Esto es una mala idea para par�metros normales, pero podr�a usarse para ficheros descargados o datos POST que est�n siendo enviados por clientes personales en vez de formularios HTML. Observa, sin embargo, que si leemos los datos POST de esta manera, podr�an no ser encontrados por getParameter.

.�ThreeParams.java

Tambi�n puedes descargar el c�digo fuente. Nota: tambi�n usa ServletUtilities.java, mostrado anteriormente.

package hall;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

public class ThreeParams extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String title = "Reading Three Request Parameters";
    out.println(ServletUtilities.headWithTitle(title) +
                "<BODY>\n" +
                "<H1 ALIGN=CENTER>" + title + "</H1>\n" +
                "<UL>\n" +
                "  <LI>param1: "
                + request.getParameter("param1") + "\n" +
                "  <LI>param2: "
                + request.getParameter("param2") + "\n" +
                "  <LI>param3: "
                + request.getParameter("param3") + "\n" +
                "</UL>\n" +
                "</BODY></HTML>");
  }

  public void doPost(HttpServletRequest request,
                     HttpServletResponse response)
      throws ServletException, IOException {
    doGet(request, response);
  }
}

.�Salida de ThreeParams

Salida de ThreeParams

.�Ejemplo: Listar todos los Datos del Formulario

Aqu� hay un ejemplo que busca todos los nombres de par�metros que fueron enviados y los pone en una tabla. Ilumina los par�metros que tienen valor cero as� como aquellos que tienen m�ltiples valores.

Primero busca todos los nombres de par�metros mediante el m�todo getParameterNames de HttpServletRequest. Esto devuelve una Enumeration. Luego, pasa por la Enumeration de la forma est�ndard, usando hasMoreElements para determinar cuando parar y usando nextElement para obtener cada entrada. Como nextElement devuelve un Object, fuerza el resultado a String y los pasa a getParameterValues, obteniendo un array de Strings. Si este array s�lo tiene una entrada y s�lo contiene un string vac�o, el par�metro no tiene valores, y el servlet genera una entrada "No Value" en it�lica. Si el array tiene m�s de una entrada, el par�metro tiene m�ltiples valores, y se muestran en una lista bulleteada. De otra forma, el �nico valor principal se s�tua en la tabla.

.�ShowParameters.java

Tambi�n puedes descargar el c�digo fuente. Nota: tambi�n usa ServletUtilities.java, mostrado anteriormente.

package hall;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;

/** Shows all the parameters sent to the servlet via either
 *  GET or POST. Specially marks parameters that have no values or
 *  multiple values.
 *  
 *  Part of tutorial on servlets and JSP that appears at
 *  http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/
 *  1999 Marty Hall; may be freely used or adapted.
 */

public class ShowParameters extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    String title = "Reading All Request Parameters";
    out.println(ServletUtilities.headWithTitle(title) +
                "<BODY BGCOLOR=\"#FDF5E6\">\n" +
                "<H1 ALIGN=CENTER>" + title + "</H1>\n" +
                "<TABLE BORDER=1 ALIGN=CENTER>\n" +
                "<TR BGCOLOR=\"#FFAD00\">\n" +
                "<TH>Parameter Name<TH>Parameter Value(s)");
    Enumeration paramNames = request.getParameterNames();
    while(paramNames.hasMoreElements()) {
      String paramName = (String)paramNames.nextElement();
      out.println("<TR><TD>" + paramName + "\n<TD>");
      String[] paramValues = request.getParameterValues(paramName);
      if (paramValues.length == 1) {
        String paramValue = paramValues[0];
        if (paramValue.length() == 0)
          out.print("<I>No Value</I>");
        else
          out.print(paramValue);
      } else {
        out.println("<UL>");
        for(int i=0; i<paramValues.length; i++) {
          out.println("<LI>" + paramValues[i]);
        }
        out.println("</UL>");
      }
    }
    out.println("</TABLE>\n</BODY></HTML>");
  }

  public void doPost(HttpServletRequest request,
                     HttpServletResponse response)
      throws ServletException, IOException {
    doGet(request, response);
  }
}

.�ShowParameters

Aqu� tenemos un formulario HTML que env�a un n�mero de par�metros a este servlet. Pulsa con el bot�n derecho sobre el enlace al c�digo fuente para descargar el HTML.

Usa POST para enviar los datos (como deber�an hacerlo todos los formularios que tienen entradas PASSWORD), demonstrando el valor de que los servlets incluyan tanto doGet como doPost.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
  <TITLE>A Sample FORM using POST</TITLE>
</HEAD>

<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">A Sample FORM using POST</H1>

<FORM ACTION="/servlet/hall.ShowParameters"
      METHOD="POST">
  Item Number:
  <INPUT TYPE="TEXT" NAME="itemNum"><BR>
  Quantity:
  <INPUT TYPE="TEXT" NAME="quantity"><BR>
  Price Each:
  <INPUT TYPE="TEXT" NAME="price" VALUE="$"><BR>
  <HR>
  First Name:
  <INPUT TYPE="TEXT" NAME="firstName"><BR>
  Last Name:
  <INPUT TYPE="TEXT" NAME="lastName"><BR>
  Middle Initial:
  <INPUT TYPE="TEXT" NAME="initial"><BR>
  Shipping Address:
  <TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
  Credit Card:<BR>
    <INPUT TYPE="RADIO" NAME="cardType"
                     VALUE="Visa">Visa<BR>
    <INPUT TYPE="RADIO" NAME="cardType"
                     VALUE="Master Card">Master Card<BR>
    <INPUT TYPE="RADIO" NAME="cardType"
                     VALUE="Amex">American Express<BR>
    <INPUT TYPE="RADIO" NAME="cardType"
                     VALUE="Discover">Discover<BR>
    <INPUT TYPE="RADIO" NAME="cardType"
                     VALUE="Java SmartCard">Java SmartCard<BR>
  Credit Card Number:
  <INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
  Repeat Credit Card Number:
  <INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
  <CENTER>
    <INPUT TYPE="SUBMIT" VALUE="Submit Order">
  </CENTER>
</FORM>

</BODY>
</HTML>
Imágen del formulario

.�Resultados del env�o

Resultado del envio

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR