Neste artigo iremos mostrar a importância de se conhecer bem os Servlets, até pelo fato de serem a base para muitos frameworks utilizados atualmente, como o JSF e Struts. Para isso, iremos objetivamente mostrar as principais características e o ciclo de vida desses objetos Java de tanta importância. Por fim, iremos construir um exemplo simples ao final do artigo.

Os Servlets foram a primeira maneira de criar páginas dinâmicas com Java. Seu nome vem da ideia de um pequeno servidor (servidorzinho, em inglês). Sua principal função é receber chamadas HTTP, processá-las e devolver uma resposta ao cliente. Para uma primeira noção de um servlet, vamos considerar que cada um é responsável por uma página, lendo os dados de uma requisição do cliente e respondendo com outros dados (uma página HTML, uma imagem GIF, etc). Como em Java tentamos sempre trabalhar com orientação a objetos, nada mais natural que um servlet seja representado como um objeto a partir de uma classe Java. Sendo assim, um servlet é, portanto, um objeto Java que recebe requisições (request), e retorna algo (response).

A figura abaixo mostra clientes (browsers) acessando o mesmo servidor através do protocolo HTTP. Note que o Servidor (na figura, o Apache Tomcat), é ao mesmo tempo um Servidor Web e um Servlet Container.

Requisições feitas a um Web Container (Servidor Web + Servlet Container)
Figura 1. Requisições feitas a um Web Container (Servidor Web + Servlet Container)

Um Servidor Web é responsável por tratar, entre outras coisas, as requisições HTTP feitas a ele. Ao recebê-las, ele as direciona para que um Servlet específico cuide delas. Mas somente o Servlet não é capaz de fazer esse serviço. Ele precisa de alguém para ajuda-lo, mais precisamente, para gerencia-lo. Esse alguém é o Servlet Container. O Servlet Container é responsável por gerenciar o ciclo de vida de um Servlet. Ele que decide quando o Servlet vai ser iniciado, através do método init(), quando vai poder atender às requisições, pelo método service(), e quando deve morrer, através do método destroy(). O Servlet somente é inicializado e destruído uma única vez, porém pode atender diversas requisições, ou seja, executar o método service() inúmeras vezes. A figura 2 mostra o ciclo de vida de um servlet, e a figura 3 mostra o diagrama de transição de estado de um Servlet, dentro do Servlet Container.

Ciclo de vida de um Servlet
Figura 2. Ciclo de vida de um Servlet
Diagrama de Transição de Estado de um Servlets
Figura 3. Diagrama de Transição de Estado de um Servlets

Para entender o diagrama de transição de estado de um servlet, precisamos entender também a sua relação com o Servlet container. No momento que o Servlet Container não está disponível, ou seja, está em shutdown (“desligado”), o servlet encontra-se DESCARREGADO. Quando ocorre o startup do Servlet Container, o Servlet é CARREGADO, porém ainda está indisponível. No momento que uma requisição chega ao Servidor Web, e é direcionada para o Servlet, o método init() é chamado e o Servlet é INICIALIZADO. Após isso, o método service() pode ser chamado inúmeras vezes e diversas requisições podem ser atendidas, até o método destroy() ser chamado e o Servlet é DESTRUIDO.

Normalmente, nas aplicações convencionais, o próprio Servlet Container é responsável por gerenciar este ciclo de vida, porém é possível que esses métodos sejam sobrecarregados, e uma nova implementação pode ser realizada. Em uma aplicação convencional, o Servlet Container executa o método service( ), e este, entre outras coisas, chama o nosso método doGet().

No nosso exemplo, vamos construir uma aplicação e sobrecarregar os métodos init(), service() e destroy(). Para isso, crie um Dynamic Web Project no Eclipse, e no Deployment Descriptor (web.xml), vamos registrar o nosso Servlet.


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 
  <servlet>
  	<servlet-name>servlet</servlet-name>
  	<servlet-class>br.com.SimpleServlet</servlet-class>
  </servlet>
  
  <servlet-mapping>
  	<servlet-name>servlet</servlet-name>
  	<url-pattern>/servlet</url-pattern>
  </servlet-mapping>
  
</web-app> 
Listagem 1. Deployment Descriptor do nosso exemplo

Pelo nosso Deployment Descriptor, vemos que temos um Servlet apelidado de, vejam só, servlet (bem criativo). Esse apelido é usado para representar nossa classe Java br.com.SimpleServlet, e para ser utilizado em outros pontos dentro do próprio web.xml. Ele será utilizado dentro do mapeamento do servlet, para definir a URL onde será acessado. Essa URL, é a /servlet. A listagem 2 mostra nossa Classe Java.


package br.com;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServlet extends HttpServlet {

	public void init() throws ServletException {
		super.init();
		System.out.println("INICIALIZANDO SERVLET");
	}

	protected void service (HttpServletRequest request,HttpServletResponse response) 
	throws ServletException, IOException {
			 PrintWriter out = response.getWriter();

			 out.println("<html>");
			 out.println("<body>");
			 out.println("Meu Servlet");
			 out.println("</body>");
			 out.println("</html>");
			 destroy();
  }
	
	public void destroy() {
		super.destroy();
		System.out.println("DESTRUINDO PARCIALMENTE O SERVLET");
	}
	
}
Listagem 2. Classe Java SimpleServlet que estende HTTPServlet

Normalmente deixamos esses métodos a cargo do próprio Servlet Container para gerenciá-lo, tanto pela complexidade, quanto por não ser necessário os sobrescrevermos. O mais importante é implementarmos os métodos HTTP, ou GET com o doGet(), ou o POST, com o doPost(). A listagem 3 mostra o exemplo de um Servlet implementando o método doGet(). Lembre-se apenas de mapeá-lo no web.xml.


package br.com;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class SimpleServletGET extends HttpServlet {

	protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
	throws ServletException, IOException {
		PrintWriter out = resp.getWriter();

	 	out.println("<html>");
	 	out.println("<body>");
	 	out.println("Meu Servlet com GET");
	 	out.println("</body>");
	 	out.println("</html>");
	}
	
}
Listagem 3. Classe Java SimpleServlet que estende HTTPServlet

Bom pessoal, ficamos por aqui. Até um próximo post, abraço.