Está en la página 1de 11

Programacin de Servlets

Introduccin

En esta parte del tutorial se vern en que partes se descompone un


servlet, el ciclo de vida de un servlet y como pasar parmetros a un
servlet desde un formulario HTML.
Inicio
1 El Servlet HolaMundo
Instalacin
En la seccin de compilacin y ejecucin de servlets creamos un
Compilar/Ejecutar servlet llamado HolaMundo.java cuyo cdigo fuente era el
siguiente:
Servlets Java
import javax.servlet.*;
import javax.servlet.http.*;
JDBC import java.io.*;

public class HolaMundo extends HttpServlet {


Ejemplos
public void init(ServletConfig conf)
Fuentes throws ServletException {
super.init(conf);
}

public void service(HttpServletRequest req,


Fco. Javier Garca HttpServletResponse res)
Castellano throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();

out.println("<html>");
out.println("<body>");
out.println("<h1>Hola Mundo</h1>");
out.println("</body>");
out.println("</html>");
}
}

Comentemos un poco nuestro este primer servlet. Lo primero que


nos aparece son las clases que utiliza (las bibliotecas o includes de
C):

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

Vemos que utiliza las clases correspondientes a servlets


(javax.servlet.*), las clases correspondientes a servlets que utilizan
el protocolo HTTP (javax.servlet.http.*). El protocolo HTTP es el
protocolo estndar en la web (o WWW - World Wide Web). Por
eso, cuando en un navegador abrimos una direccin, la mayora
empieza por http://. Tambin utiliza clases de entrada/salida
(java.io.* - io viene input/output) para poder escribir en pantalla.

Lo segundo que vemos es el nombre de la clase (class HolaMundo)


que es pblica (public), en el sentido de que cualquiera puede
usarla sin ningn tipo de restriccin) y que hereda (extends) de la
clase HttpServlet.

public class HolaMundo extends HttpServlet {

Algo que debemos saber es que toda clase, para que se considere
un servlet, debe implementar el interfaz javax.servlet.Servlet. Para
conseguirlo lo ms sencillo es hacer que nuestra clase herede o
bien de la clase javax.servletGenericServlet o
javax.servlet.http.HttpServlet. Con la primera obtendremos un
servlet independiente del protocolo, mientras que con la segunda
tendremos un servlet HTTP. En este tutorial, slo vamos a ver
servlets que funcionen con el protocolo HTTP as que, por tanto,
siempre heredarn de HttpServlet. Resumiendo, slo cambiar el
nombre de la clase para cada servlet que hagamos.

El siguiente trozo de cdigo que aparece (y que tenemos que


implementar siempre) es la redefinicin del mtodo init. El
servidor invoca a este mtodo cuando se crea el servlet y en este
mtodo podemos hacer todas las operaciones de inicializacin que
queramos. Como en este servlet no nos hace falta inicializacin
ninguna, lo nico que hacemos es llamar al mtodo init por defecto
(al de la superclase).

public void init(ServletConfig conf)


throws ServletException {
super.init(conf);
}

Podemos observar que el mtodo init es pblico, no devuelve


ningn tipo (void), que puede lanzar una excepcin
(ServletException) y que tiene un parmetro (ServletConfig conf).
De estos dos ltimos aspectos (excepcin y parmetro) no nos
tenemos que preocupar pues es el servidor quien ejecuta el mtodo
init. En el peor de los casos, tendramos que lanzar la excepcin (si
sabemos hacerlo), si por algn motivo el mtodo init que nosotros
implementemos falle (por ejemplo, que no se pueda conectar a la
base de datos y evitamos mostrar un mensaje de error)

Lo siguiente que hacemos redefinir el mtodo service, cuando el


servidor web recibe una peticin para un servlet llama al mtodo
public void service(HttpServletRequest req, HttpServletResponse
res) con dos parmetros: el primero, de la clase
HttpServletRequest, representa la peticin del cliente y el
segundo, de la clase HttpServletResponse, representa la respuesta
del servidor (del servlet, ms concretamente).

public void service(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();

out.println("<html>");
out.println("<body>");
out.println("<h1>Hola Mundo</h1>");
out.println("</body>");
out.println("</html>");
}

Como en este primer ejemplo no necesitamos ninguna informacin


del cliente, no usaremos para nada el parmetro
HttpServletRequest, ms adelante veremos como hacerlo. De la
clase HttpServletResponse usamos dos mtodos:

setContextType(String str) para establecer el tipo de


respuesta que vamos a dar. Para indicar que se trata de una
pgina web, como haremos siempre, usamos el tipo
"text/html".
res.setContentType("text/html");
PrinterWriter getWriter(void) con el que obtendremos
una clase PrinterWriter en donde iremos escribiendo los
datos que queremos que el cliente reciba (como podra ser
el stdout de C o el cout de C++):

PrintWriter out = res.getWriter();

Una vez que hemos establecido el tipo de respuesta (text/html)y


tenemos el flujo de salida (variable out) slo nos queda utilizar el
mtodo println de la clase PrinterWriter para ir escribiendo en
dicho flujo de salida la pgina HTML que queremos que visualice
el cliente.
2 Servlet GetPost

Vamos a ver un ejemplo, un poco ms complicado. Si llamamos un


servlet desde un formulario HTML, podremos hacerlo de dos
formas: GET y POST. Con la primera los parmetros del
formulario estn incluidos la url que se utiliza para invocar el
servlet y en el segundo caso los parmetros se almacenan en un
buffer especial del servidor.

Para procesar el primer tipo de peticiones (GET) est el mtodo


doGet mientras que para el segundo tenemos el mtodo doPost .
La implementacin por defecto del mtodo service es capaz de
determinar el tipo de peticin HTTP que en un momento dado
recibe el servlet. Una vez identificada llama o al mtodo doGet o
al doPost segn el caso. Como, en la mayora de los casos,
seremos nosotros quien programe el formulario que llame al
servlet, sabremos que tipo de llamada se har, por lo que podemos
optar por redefinir uno slo de los mtodos. En el caso de que no lo
supiramos se deben implementar los mtodos doGet y doPost.

Un servlet que tiene diferente respuesta en funcin de la llamada


que se le hace es el ejemplo GetPost.java cuyo cdigo fuente era
el siguiente:

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

public class GetPost extends HttpServlet {

public void init(ServletConfig conf)


throws ServletException {
super.init(conf);
}

public void doGet(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<h1>Hola Mundo (llamada GET)</h1>");
out.println("</body>");
out.println("</html>");
}

public void doPost(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException
{
res.setContentType("text/html");
PrintWriter out = res.getWriter();
out.println("<html>");
out.println("<body>");
out.println("<h1>Hola Mundo (llamada POST)</h1>");
out.println("</body>");
out.println("</html>");
}
}

Para llamar al servlet con un tipo de llamada get, podemos usar el


ejemplo get.html. Que podemos colocar en el directorio
C:\java\tomcat\webapps\tutorial\ y cuyo cdigo es:

<html>
<body>
<h1>Mtodo GET</h1>
<form method="GET"
action="/tutorial/servlet/GetPost">
<input type="submit">
</form>
</body>
</html>

Para llamar al servlet con un tipo de llamada post, podemos usar el


ejemplo post.html. Que podemos colocar en el directorio
C:\java\tomcat\webapps\tutorial\ y cuyo cdigo es:

<html>
<body>
<h1>Mtodo POST</h1>
<form method="POST"
action="/tutorial/servlet/GetPost">
<input type="submit">
</form>
</body>
</html>

3 Ciclo de vida de un Servlet

Como hemos visto antes, cuando se crea un servlet, el servidor


llama al mtodo init y cada vez que un cliente acceda al servlet el
servidor llamar al mtodo service que se encargar de redirigir la
llamada doGet o a doPost. Esto nos quiere decir que cuando se
llama por primera vez a un servlet se ejecutara primero init y
despus service, pero ... Y la segunda vez y sucesivas tambin se
llama a init o slo a service?.

Normalmente, el servidor crea el servlet (llama, por tanto, al


mtodo init) y lo mantiene funcionando, si ha pasado un tiempo
suficiente (y que puede ir desde unos segundos a nunca) sin que el
servlet se llame lo deja de ejecutar. Es decir, un servlet se empieza
a ejecutar con la primera llamada y, normalmente, se seguir
ejecutando.

De esta forma, vamos a crear un servlet que cuente el nmero de


visitas que recibe, para ello nos bastar crear una variable contador
que inicializaremos en el mtodo init y que incrementaremos en
doPost/doGet. Por lo que, el contador se inicializar cuando se
llame por primera vez al servlet y se ir incrementando en llamadas
sucesivas. Este ejemplo, lo llamaremos Contador.java y su cdigo
fuente era el siguiente:

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

public class Contador extends HttpServlet {


//variable contador
int contador;

public void init(ServletConfig conf)


throws ServletException {
super.init(conf);

//inicializamos la variable contador


contador = 1;
}

public void doGet(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();
int tmp = contador;

//incrementamos la variable contador


contador++;

out.println("<html>");
out.println("<body>");
out.println("<h1>Numero de peticiones " + tmp
+"</h1>");
out.println("</body>");
out.println("</html>");
}

public void doPost(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {
doGet(req, res);
}
}
NOTA: Observa que un mismo servlet puede ser llamado por ms
de un cliente a la vez. En este caso, el servidor crea una hebra del
servlet por cada peticin y esas dos hebras accedern
concurrentemente a los mismos datos (la variable contador). Como
la lectura e incremento de contador no es una operacin atmica, se
podra utilizar la primitiva de sincronizacin syncronized para que
se realice de forma atmica:

.....
PrintWriter out = res.getWriter();
int tmp;

synchronized(this) {
//leemos el contador
tmp = contador;
//incrementamos la variable contador
contador++;
}

out.println("<html>");
.....

4 Parmetros desde un formulario HTML

Normalmente los servlets tendrn parmetros o fuentes de


informacin que le darn su aspecto dinmico. Es decir, para
generar una simple pgina HTML no nos complicamos tanto la
vida, se escribe la pgina HTML y se ha terminado. Las fuentes de
informacin de las que un servlet hace uso, pueden ser varias: el
propio servlet, el servidor web, ficheros o bases de datos a los que
pueda acceder o parmetros que le pase el cliente. De todas estas
fuentes, nos interesan los accesos a bases de datos que veremos
ms adelante y los pa;rmetros que nos pasa el cliente mediante
formularios HTML.

Cuando pasamos parmetros a travs de un formulario, en los


Servlets a travs de la clase ServletRequest, disponemos de los
siguientes mtodos para su tratamiento:

String getParameter(String nombre): Nos devuelve el


valor del parmetro cuyo nombre le indicamos. Si la
variable no existiera o no tuviese ningn valor, devolvera
null
Enumerate getParameterNames(): Nos devuelve una
enumeracin de los nombres de los parmetros que recibe
el servlet.
Enumerate getParameterValues(String): Nos devuelve
los valores que toma un parmetro dado, esto es til para
listas de seleccin mltiple donde un parmetro tiene ms
de un valor.

Veamos un ejemplo de un pequeo formulario que tenga distintos


tipos de parmetros, se los enve a nuestro servlet y ste los
muestre por pantalla (an no sabemos guardarlos en la base de
datos). El formulario los llamaremos formulario.html. Que
podemos colocar en el directorio
C:\java\tomcat\webapps\tutorial\ y cuyo cdigo es:

<html>
<title>Formulario de ejemplo</title>
<body>
<h1>Formulario</h1>
<form method="POST"
action="/tutorial/servlet/Parametros">
Nombre: <INPUT TYPE="TEXT" NAME="nombre"><BR>
Primer Apellido:<INPUT TYPE="TEXT"
NAME="apellido1"><BR>
Segundo Apellido:<INPUT TYPE="TEXT"
NAME="apellido2"><BR>
<hr>
Correo electronico: <INPUT TYPE="TEXT"
NAME="email"><BR>
Clave: <INPUT TYPE="PASSWORD" NAME="clave"><BR>
<hr>
Comentario: <TEXTAREA NAME="comenta" ROWS=3
COLS=40>
</TEXTAREA><BR>
<hr>
Sexo:<BR>
<INPUT TYPE="RADIO" NAME="sexo"
VALUE="hombre">Hombre<BR>
<INPUT TYPE="RADIO" NAME="sexo"
VALUE="mujer">Mujer<BR>

Areas de inters:<br>
<SELECT NAME="intereses" MULTIPLE>
<OPTION>Informatica</OPTION>
<OPTION>Derecho</OPTION>
<OPTION>Matematicas</OPTION>
<OPTION>Fisica</OPTION>
<OPTION>Musica</OPTION>
</SELECT>

<center><input type="submit"
value="Enviar"></center>
</form>
</body>
</html>

Veamos primero un servlet que conociendo de antemano los


distintos parmetros que va a recibir los vaya mostrando en una
pgina HTML. El servlet lo llamaremos Parametros.java y su
cdigo es:

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

public class Parametros extends HttpServlet {

public void init(ServletConfig conf)


throws ServletException {
super.init(conf);
}

public void doGet(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
PrintWriter out = res.getWriter();

out.println("<html>");
out.println("<body>");
out.println("<h1>Parmetros del servlet desde un
formulario HTML</h1>");
out.println("<br>
Nombre:"+req.getParameter("nombre") );
out.println("<br> Primer
apellido:"+req.getParameter("apellido1") );
out.println("<br> Segundo
apellido:"+req.getParameter("apellido2") );
out.println("<br> Correo
electrnico:"+req.getParameter("email") );
out.println("<br>
Contrasea:"+req.getParameter("clave") );
out.println("<br>
Comentario:"+req.getParameter("comenta") );
out.println("<br> Sexo:"+req.getParameter("sexo")
);
out.println("<br> Areas de
inters:"+req.getParameter("intereses") );
out.println("</body>");
out.println("</html>");
}

public void doPost(HttpServletRequest req,


HttpServletResponse res)
throws ServletException, IOException {
doGet(req, res);
}
}

Si en la lista de de seleccin mltiple escogemos ms de un valor


en la implementacin actual slo mostrara la primera eleccin, si
quisiramos mostrar todos los valores deberamos de usar
getParameterValues("intereses") e ir recorriendo y mostrando
cada uno de los valores seleccionados del parmetro intereses.

Otra posible implementacin del servlet Parametros.java sera


uno que mostrase los parmetros y sus valores sin tener que
conocerlos previamente. El cdigo sera:

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

public class Parametros extends HttpServlet


{
public void init(ServletConfig conf)
throws ServletException
{
super.init(conf);
}

public void doGet(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();

//Escribimos el principio de la pgina HTML


out.println("<html>");
out.println("<body>");
out.println("<h1>Parmetros del servlet desde un
formulario HTML</h1>");

//cogemos los nombres de los parametros


Enumeration paramNames =
request.getParameterNames();

//vamos mostrando los parmetros en unwhile


while(paramNames.hasMoreElements()) {
//cogemos el siguiente parmetro
String paramName =
(String)paramNames.nextElement();

//Mostramos el nombre del parmetro


out.print(paramName + " = ");

//Cogemos los valores del parmetro


String[] paramValues =
request.getParameterValues(paramName);

//Miramos si tiene ms de un valor


if (paramValues.length == 1) {
//Si tiene un slo valor, miramos si est
vaco o no
String paramValue = paramValues[0];
if (paramValue.length() == 0)
out.println("<i>Sin valor</i><br>");
else
out.println(paramValue + "<br>");
}
else {
//Si tiene ms de un slo valor, los mostramos
for(int i=0; i<paramValues.length; i++)
out.println(paramValues[i] + ", ");
out.println("<br>");
}
}//end while

//Escribimos el final de la pgina HTML


out.println("</body>");
out.println("</html>");
}

public void doPost(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

También podría gustarte