En breve: un servlet es un programa ejecutado en el servidor (a diferencia de los applets que se ejecutan en el cliente). Es un mecanismo para implantar aplicaciones en el lado del servidor. Reciben peticiones y mandan resultados en HTTP, siendo el formato más común de salida una página HTML o un archivo XML (pero puede ser cualquier tipo MIME, una imagen, un objeto serializado, etc).
Antes de aprender sobre servlets conviene entender lo que es un servidor de aplicaciones: Capítulo de Arquitectura JEE - Servidor de aplicaciones.
Un primer ejemplo de servlet: Capítulo de Arquitectura JEE - Servlets.

El proceso de ejecución de un servlet:

Cada petición genera un hilo independiente. Pero sólo la primera petición genera una instancia de la clase servlet. Podremos tener N peticiones al servlet, por tanto N hilos, pero únicamente una instancia de la clase (un objeto).
El esquema es muy parecido al que existe en el CGI (Common Gateway Interface). Ventajas de los servlets:
Para la instalación de un servidor de aplicaciones como Tomcat: Capítulo de Herramientas - Tomcat.
El API para programar Servlets no forma parte del núcleo JDK (Standard Edition) y hay que descargarlo (a menos que use la Enterprise Edition o que haya sido instalado por el entorno de programación que este utilizando). Viene suministrado también por Tomcat en el directorio common/lib. En el siguiente ejemplo lo hemos descargado de (SUN) y lo hemos puesto en el directorio ext del JRE, con la ventaja de que lo reconoce de forma automática el IDE Eclipse:
A la hora de programar los paquetes necesarios son:
javax.servlet javax.servlet.http
Los servlets HTTP derivan de la clase javax.servlet.http.HttpServlet. Esta clase deriva de la clase javax.servlet.GenericServlet, que a su vez implementa javax.servlet.Servlet. La clase HttpServlet sobreescribe el método service() de forma que puede manejar diferentes tipos de solicitudes HTTP: DELETE, GET, OPTIONS, POST, PUT, y TRACE. Por cada uno de estos tipos de solicitud, la clase HttpServlet proporciona su correspondiente método doXXX().
Aunque podemos sobreescribir (redefinir) el método service() en nuestra clase servlet, raramente hay alguna necesidad de hacerlo. Más frecuentemente querremos redefinir métodos doXXX() individuales. Para la mayoría de las aplicaciones querremos redefinir los métodos doPost() y doGet(), ya que ellos manejan normalmente los datos enviados por un href o un formulario (FORM).
Enlace a una página sobre la creación de Servlets con JBuilder 9 Enterprise
Un primer ejemplo de servlet: Capítulo de Arquitectura JEE - Servlets.
En el siguiente ejemplo tenemos un servlet que nos saluda y cuenta las invocaciones a doGet():
package docen_servlet01;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
public class SaludoContador extends HttpServlet {
int contador = 0; // Contador de veces que se invoca doGet()
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
contador++;
out.println("<html>");
out.println("<head><title>Bienvenido al servlet contador</title></head>");
out.println("<body bgcolor=\"#FFFF9D\"><FONT color=\"#000080\" FACE=\"Arial,Helvetica,Times\" SIZE=2>"+
"<CENTER><H3>Servlets</H3></CENTER>");
Date d = new Date();
out.println("<HR><p>¡Hola Mundo!. Fecha y hora: " + d.toString() + "</p>");
out.println("<p>Número de invocaciones a doGet(): " + contador + "</p>");
out.println("</body></font></html>");
}
}
El formulario puede ser:
<form action="../../servlet/saludo_contador" method="get"> <p><input type="submit" name="Submit" value="Pulse Enviar para llamar al servlet que saluda y cuenta"></p> </form>
Ejemplo "real" del servlet:
En este ejemplo la aplicación se llama public_html, de la que cuelgan los directorios:
La invocación al servlet se hace desde el atributo action del form. Incluye una dirección relativa ("../../servlet/saludo_contador"). La expresión "../.." es tanto como decir "public_html", es decir, el contexto raíz de nuestra aplicación. Por ello, sería lo mismo decirle en forma absoluta http://localhost:puerto/public_html/servlet/saludo_contador.
Una aplicación al menos se compone de:
Cada aplicación tiene que tener una estructura de directorios predeterminada. Empieza por un directorio raíz del contexto de aplicación, por ejemplo public_html, cuya URL sería http://www.host.com/public_html. Suele ser habitual tener el archivo index.jsp o index.html en este directorio (pero no obligatorio). Los subdirectorios que parten de este directorio raíz serán:
En WEB-INF se encuentra el archivo web.xml, donde se indican los Servlets contenidos en la aplicación. Hablaremos de este archivo cuando tengamos que referirnos a la instalación de los servlets. Por cierto, para hablar de forma estricta se dice "despliegue" (deployment) y no "instalación". Otro aspecto interesante, además del archivo web.xml, es que los servlets están físicamente en WEB-INF/classes (si son .class) o en WEB-INF/lib (si son .jar). Ver como ejemplo examples/WEB-INF/classes, que viene por defecto en nuestra versión de Tomcat; donde no hay librerias y por tanto no hay directorio lib. Existe un directorio WEB-INF, ya que resulta imprescindible como receptáculo de web.xml y del directorio classes:
En realidad de WEB-INF puede colgar cualquier subdirectorio (hay quien pone el código fuente en un subdirectorio src).
Notas dignas de tener en cuenta:
Ya tenemos los archivos necesarios: .class y .html. Ahora de lo que se trata es de desplegar la aplicación, es decir, instalarlo en nuestro servidor de aplicaciones.
En el siguiente caso vamos a seguir el ejemplo de SaludoContador.class, que pertenece a la aplicación cuyo directorio "físico" es c:/web/public_html y su URL es http://localhost:puerto/public_html.
Ahora necesitamos señalar al servidor de aplicaciones el nombre y el lugar de nuestro servlet. Para ello existe un archivo denominado "descriptor de despliegue", que tiene como nombre web.xml y está en el directorio WEB-INF. Tomcat viene con archivos web.xml para sus aplicaciones preinstaladas. En nuestro caso vamos a crear web.xml dentro de c:/web/public_html/WEB-INF:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>public_html: proactiva-calidad LOCAL</display-name>
<servlet>
<servlet-name>saludo_contador</servlet-name>
<servlet-class>docen_servlet01.SaludoContador</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>saludo_contador</servlet-name>
<url-pattern>/servlet/saludo_contador</url-pattern>
</servlet-mapping>
</web-app>
Explicación de la estructura de web.xml:
Interesa que se entienda la secuencia resumida de acciones que van desde la invocación (por ejemplo en un formulario) hasta la ejecución del servlet:
Una moraleja de esta secuencia es que el servidor separa la dirección lógica (URL) de la localización física del archivo .class. En la llamada al servlet lo primero es encontrar la URL y, una vez encontrada ésta, se localiza al servlet "físicamente". Esto permite cambiar la URL de llamada sin recompilar la clase, simplemente cambiando web.xml.
La ruta física de nuestra aplicación (c:/web/public_html) no corresponde con la URL. La URL de la aplicación es una dirección "virtual" o lógica dentro de nuestro servidor de aplicaciones y es independiente del espacio físico donde guardamos los archivos de la aplicación
En el archivo server.xml es donde configuramos las aplicaciones de nuestro servidor, entre otras cosas definiremos el directorio de los archivos y la URI de nuestra aplicación, en nuestro caso es /public_html.
Para una explicación de cómo definir una aplicación en server.xml ver el capítulo dedicado a Herramientas - Tomcat
El archivo .class del servlet se colocan en un subdirectorio de WEB-INF que se llama classes/docen_servlet01, ya que éste es el paquete de la clase. Con lo cual tendremos la clase en c:/web/public_html/WEB-INF/classes/docen_servlet01.
Aplicando todo lo indicado escribimos en server.xml:
.... <Context path="/public_html" reloadable="true" docBase="C:\DOC\Java_eclipse\public_html" /> </Host> </Engine> </Service> </Server>
Un consejo de prudencia: antes de tocar server.xml haga una copia de respaldo del original.
Todo lo dicho corresponde a nuestra versión de Tomcat, pero puede cambiar en otras y también depende de si tenemos configurados servidores virtuales. Nuestra aplicación ("context" en la jerga Tomcat) la instalaremos dentro del host por defecto. Para ello, tenemos que buscar en el final de server.xml, justo antes de </host>.
Una buena noticia: esta modificación del archivo server.xml la suelen realizar la mayor parte de IDEs. Por ejemplo en Eclipse o JBuilder se modifica el archivo introduciendo como nombre de la aplicación el nombre del proyecto. En Eclipse es necesario indicar a la hora de crear un proyecto que el tipo de proyecto es un "Tomcat project".
Un aspecto que a menudo se olvida es que el despliegue del servlet exige (en general, depende de la configuración del servidor) una recarga de la aplicación. En algunas instalaciondes del servidor de aplicaciones, la recarga puede producirse de forma automática cuando el servlet y el web.xml son modificados (depende del correcto funcionamiento del atributo reloadable=true). Sin embargo en muchos casos se exige una recarga manual. Si en la invocación al servlet aparece el siguiente código de error:
The requested resource (/Nombre_del_Servlet) is not available.
La solución (presuponiendo que se ha editado web.xml y server.xml correctamente) está en la mayoría de los casos en entrar en el Manager del servidor de aplicaciones y recargar (reload) la aplicación correspondiente. Para acceder al manager en una instalación estándar de Tomcat: http://localhost:8080/manager/html. Si esto último no funciona y empieza a desesperarse reinicie el servicio Tomcat desde el sistema operativo.
Por ultimo, para comprobar que todo ha ido bien se puede probar a hacer desde el navegador: http://localhost:8080/public_html/servlet/saludo_contador. En cuento esto funcione podemos probarr con nuestro formulario. Si el formulario no invoca al servlet, probablemente el error sea que no se ha introducido correctamente la ruta del servlet en el atributo action del formulario o que no se usa el método HTTP correcto (post, get, etc.).
Un enlace que explica en mayor detalle el despliegue de servlets y los archivos WAR.
Existen dos métodos de despliegue: