Gerar imagens dinâmicas com servlets

HTTP Servlets tem utilidade mais interessante do que apenas Front Controllers e gerar código HTML. Um dos recursos mais bacanas é a possibilidade de gerar conteúdo binário em tempo de execução. Nesse post demonstrarei como desenhar uma imagem dinâmica utilizando Servlets. A idéia veio da necessidade do Cássio em extrair páginas de PDF e exibir como imagens em uma aplicação Web.

Vamos criar uma Servlet onde o usuário poderá realizar uma requisição via GET da URL "imagem.png" passando um parâmetro "texto" e a Servlet irá retornar uma imagem com uma bolinha e o texto digitado.

Estou utilizando Servlet 3.0, mas o código do método get pode ser utilizado em qualquer outra versão de Servlets sem necessidade de alteração.

package br.com.thiagovespa.samples.imagem;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Gera uma imagem com um texto passado por parâmetro
 *
 * @author Thiago Galbiatti Vespa
 */
@WebServlet("/imagem.png")
public class ImagemServlet extends HttpServlet {

	private static final long serialVersionUID = 201011231103L;

	public ImagemServlet() {
		super();
	}

	@Override
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// A imagem é um png - Poderia ser qualquer outro tipo
		response.setContentType("image/png");

		// Recupera o parâmetro
		String text = request.getParameter("texto");

		// Cria uma imagem de tamanho 500x50
		BufferedImage image = new BufferedImage(500, 50,
				BufferedImage.TYPE_INT_ARGB);

		// Cria o canvas pra desenho
		Graphics2D canvas = image.createGraphics();
		canvas.setColor(Color.BLUE);
		// Desenha um círculo azul
		canvas.fillOval(10, 10, 10, 10);
		canvas.setColor(Color.RED);
		canvas.setFont(new Font(Font.SANS_SERIF, Font.BOLD, 14));
		// Desenha o texto em vermelho
		canvas.drawString(text != null ? text : "Nenhum texto informado!", 25,
				20);
		OutputStream out = null;
		try {
			out = response.getOutputStream();
			// Escreve a imagem no outputstream da response no formato png
			ImageIO.write(image, "PNG", out);
		} finally {
			if (out != null) {
				out.close();
			}
		}
	}

}

Fiz vários comentários no código para facilitar a compreensão de quem está começando e para eu não precisar explicar linha a linha o que o código está fazendo :). O código importante  para gerar qualquer conteúdo binário é o que está destacado na linha 35, que seta o mime-type correto para a servlet exibir e o da linha 56 que recupera o OutputStream (binário) para escrever algum conteúdo nele.

Para utilizar o mime-type correto pro seu tipo de conteúdo, você pode utilizar a tabela da W3School disponível nesse link: http://www.w3schools.com/media/media_mimeref.asp

Agora é só fazer o deploy de um projeto com essa Servlet e acessá-la passando um parâmetro. O resultado você pode ver na imagem abaixo:

imagem.png (500×50)
imagem.png (500×50)

Para exibir dentro de uma página HTML é só referenciar o endereço da Servlet no atributo src da tag img. Por exemplo:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Exemplo imagem</title>
</head>
<body>
Olha minha imagem a&iacute; em baixo<br/>
<img src="imagem.png?texto=Imagem gerada!"/>
</body>
</html>

O browser irá exibir o conteúdo da imagem gerada dinâmicamente:

Exemplo imagem
Exemplo imagem

Agora é só programar a Servlet para gerar o que você quiser!.

Esse conceito é utilizado para geração de CAPTCHAs, PDF, XLS, e outros arquivos binários dinamicamente.

Sobre: Thiago Galbiatti Vespa

Thiago Galbiatti Vespa é mestre em Ciências da Computação e Matemática Computacional pela USP e bacharel em Ciências da Computação pela UNESP. Coordenador de projetos do JavaNoroeste, membro do JCP (Java Community Process), consultor Oracle, arquiteto de software de empresas de médio e grande porte, palestrante de vários eventos e colaborador de projetos open source. Possui as certificações: Oracle Certified Master, Java EE 5 Enterprise Architect – Step 1, 2 and 3; Oracle WebCenter Portal 11g Certified Implementation Specialist; Oracle Service Oriented Architecture Infrastructure Implementation Certified Expert; Oracle Certified Professional, Java EE 5 Web Services Developer; Oracle Certified Expert, NetBeans Integrated Development Environment 6.1 Programmer; Oracle Certified Professional, Java Programmer; Oracle Certified Associate, Java SE 5/SE 6