Servelts y JSP

Primeros Servlets


  1. Estructura Básica de un Servlet
  2. Un sencillo Servlet que Genera Texto Normal
  3. Un Servlet que Genera HTML
  4. Utilidades de Construcción de HTML Sencillo

1. Estructura Básica de un Servlet

Aquí tenemos un servlet básico que maneja peticiones GET. Las peticiones GET, para aquellos que no estemos familiarizados con HTTP, son peticiones hechas por el navegador cuando el usuario teclea una URL en la línea de direcciones, sigue un enlace desde una página Web, o rellena un formulario que no especifica un METHOD. Los Servlets también pueden manejar peticiones POST muy fácilmente, que son generadas cuando alguien crea un formulario HTML que especifica METHOD="POST". Los discutiremos en una sección posterior.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SomeServlet extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
      
    // Use "request" to read incoming HTTP headers (e.g. cookies)
    // and HTML form data (e.g. data the user entered and submitted)
    
    // Use "response" to specify the HTTP response line and headers
    // (e.g. specifying the content type, setting cookies).
    
    PrintWriter out = response.getWriter();
    // Use "out" to send content to browser
  }
}
(Descarga la plantilla de código fuente -- pulsa con el botón derecho del ratón sobre el enlace o mantén pulsada la tecla SHIFT mientras pulsas sobre el enlace).

Para ser un servlet, una clase debería extender HttpServlet y sobreescribir doGet o doPost (o ambos), dependiendo de si los datos están siendo enviados mediante GET o POST. Estos métodos toman dos argumentos: un HttpServletRequest y un HttpServletResponse.

El HttpServletRequest tiene métodos que nos permiten encontrar información entrante como datos de un FORM, cabeceras de peticiòn HTTP, etc. El HttpServletResponse tiene métodos que nos permiten especificar líneas de respuesta HTTP (200, 404, etc.), cabeceras de respuesta (Content-Type, Set-Cookie, etc.), y, todavía más importante, nos permiten obtener un PrintWriter usado para envíar la salida de vuelta al cliente. Para servlets sencillos, la mayoría del esfuerzo se gasta en sentencias println que generan la página deseada. Observamos que doGet y doPost lanzan dos excepciones, por eso es necesaria incluirlas en la declaración. También observamos que tenemos que importar las clases de los paquetes java.io (para PrintWriter, etc.), javax.servlet (para HttpServlet, etc.), y javax.servlet.http (para HttpServletRequest y HttpServletResponse). Finalmente, observamos que doGet y doPost son llamados por el método service, y algunas veces querremos sobreescribir directamente el método service, por ejemplo, para un servlet que maneje tanto peticiones GET como POST.

2. Un Sencillo Servlet que Genera Texto Normal

Aquí tenemos un servlet que sólo genera texto normal. La siguiente sección mostrará el caso más usual donde se generará HTML.

2.1 HelloWorld.java

También puedes descargar el código fuente
package hall;

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

public class HelloWorld extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    out.println("Hello World");
  }
}

2.2 Compilar e Instalar el Servlet

Debemos observar que los detalles específicos para instalar servlets varian de servidor en servidor. Los ejemplos se han probado sobre Java Web Server (JWS) 2.0, donde se espera que los servlets estén en un directorio llamado servlets en el árbol de instalación del JWS. Sin embargo, hemos situado este servlet en un paquete separado (hall) para evitar conflictos con otros servlets del servidor; querrás hacer lo mismo si usas un servidor Web que es usado por otras personas y no tiene buena estructura para "servlets virtuales" para evitar automáticamente estos conflictos. Así, HelloWorld.java realmente va en un sudirectorio llamado hall en el directorio servlets. Observa que la configuración de la mayoría de los servidores, y los ejemplos de este turtorial también se han probado usando BEA WebLogic e IBM WebSphere 3.0. WebSphere tiene un excelente mecanismo para servlets virtuales, y no es necesario usar paquetes, sólo para evitar conflictos de nombres con otros usuarios.

Una forma de configurar nuestro CLASSPATH es apuntar al directorio superior al que contiene realmente nuestros servlets. Entonces podemos compilar normalmente desde dentro del directorio. Por ejemplo, si nuestro directorio base es C:\JavaWebServer\servlets y el nombre de nuestro paquete es (y por lo tanto el del subdirectorio) es hall, y trabajamos bajo Windows, deberiamos hacer:

DOS> set CLASSPATH=C:\JavaWebServer\servlets;%CLASSPATH%
DOS> cd C:\JavaWebServer\servlets\hall
DOS> javac YourServlet.java
La primea parte, configura el CLASSPATH, probablemente querremos hacerlo permanentemente, en vez de hacerlo cada que arrancamos una nueva ventana del DOS. En Windows 95/98 pondremos la sentencia "set CLASSPATH=..." en algún lugar de nuestro fichero autoexec.bat después de la línea que selecciona nuestro CLASSPATH para apuntar a servlet.jar y jsp.jar.

Una segunda forma de compilar las clases que están en paquetes es ir al directorio superior del que contiene los servelts, y luego hacer "javac directory\YourServlet.java". Por ejemplo, supongamos de nuevo que nuestro directorio base es C:\JavaWebServer\servlets y que el nombre de nuestro paquete (y del directorio) es hall, y que estamos trabajando en Windows. En este caso, haremos los sigueinte:

DOS> cd C:\JavaWebServer\servlets
DOS> javac hall\YourServlet.java
Finalmente otra opción avanzada es mantener el código fuente en una localización distinta de los ficheros .class. y usar la opción "-d" de javac para instalarlos en la localización que espera el servidor Web.

2.3 Ejecutar el Servlet

Con el Java Web Server, los servlets se sitúan en el directorio servlets dentro del directorio principal de la instalación del JWS, y son invocados mediante http://host/servlet/ServletName. Observa que el directorio es servlets, plural, mientras que la referencia URL es servlet, singular. Como este ejemplo se situó en el paquete hall, sería invocado mediante http://host/servlet/hall.HelloWorld. Otros servidores podrían tener convenciones diferentes sobre donde instalar los servlets y como invocarlos. La mayoría de los servidores nos permiten definir alias para nuestros servlets, para que un servlet pueda ser invocado mediante http://host/any-path/any-file.html.

3. Un Servlet que Genera HTML

La mayoría de los servelts generan HTML, no texto normal como el ejemplo anterior. Para hacer esto, necesitamos dos pasos adicionales, decirle al navegador que estámos devolviendo HTML. y modificar la sentencia println para construir una página Web legal. El primer paso se hace configurando la cabecera de respuesta Content-Type. En general, las cabeceras de respuesta se configuran mendiante el método setHeader de HttpServletResponse, pero seleccionar el tipo de contenido es una tarea muy común y por eso tiene un método especial setContentType sólo para este propósito. Observa que necesitamos configurar las cabeceras de respuesta antes, de devolver algún contenido mediante PrintWriter. Aquí hay un ejemplo:

3.1 HelloWWW.java

También puedes descargar El Código fuente.
package hall;

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

public class HelloWWW extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
                                        "Transitional//EN\">\n" +
                "<HTML>\n" +
                "<HEAD><TITLE>Hello WWW</TITLE></HEAD>\n" +
                "<BODY>\n" +
                "<H1>Hello WWW</H1>\n" +
                "</BODY></HTML>");
  }
}

3.2 Resultado de HelloWWW

4. Utilidades de Construcción de HTML Sencillo

Es un poco aburrido generar HTML con sentencias println. La solución real es usar Java Server Pages (JSP), que se describen más adelante. Sin embargo, para servelts estándards, hay dos partes de la página Web que no cambian (DOCTYPE y HEAD) y que podría beneficiarnos el incluirlas en un fichero de utilidades.

La línea DOCTYPE es técnicamente requerida por la especificación HTML, y aunque la mayoría de los navegadores Web la ignoran, es muy útil cuando se envían páginas a validadores de formato HTML. Estos validadores comparan la síntasis HMTL de las páginas comparándolas con la especificación formal del HTML, y usan la línea DOCTYPE para determinar la versión de HTML con la que comparar.

En muchas páginas web, la línea HEAD no contiene nada más que el TITLE, aunque los desarrolladores avanzados podrían querer incluir etiquetas META y hojas de estilo. Pero para el caso sencillo, crearemos un método que crea un título y devuelve las entradas DOCTYPE, HEAD, y TITLE como salida. Aquí está el código:

4.1 ServletUtilities.java (Descarga el código fuente)

package hall;

public class ServletUtilities {
  public static final String DOCTYPE =
    "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">";

  public static String headWithTitle(String title) {
    return(DOCTYPE + "\n" +
           "<HTML>\n" +
           "<HEAD><TITLE>" + title + "</TITLE></HEAD>\n");
  }
  
  // Other utilities will be shown later...
}

4.2 HelloWWW2.java (Descarga el código fuente)

Aquí tenemos una nueva versión de la clase HelloWWW que usa esto.
package hall;

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

public class HelloWWW2 extends HttpServlet {
  public void doGet(HttpServletRequest request,
                    HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println(ServletUtilities.headWithTitle("Hello WWW") +
                "<BODY>\n" +
                "<H1>Hello WWW</H1>\n" +
                "</BODY></HTML>");
  }
}

Ozito