Quando um desenvolvedor Java precisa colocar uma aplicação web no ar, uma das primeiras perguntas que aparece é: “onde vou rodar esse Servlet?”. A resposta que o mercado consolidou ao longo de mais de duas décadas aponta frequentemente para o mesmo lugar: Apache Tomcat. Jenkins roda nele. Jira pode rodar nele. Alfresco usa como servidor padrão. Incontáveis aplicações corporativas ao redor do mundo executam sobre essa infraestrutura que a Apache Software Foundation distribui gratuitamente desde 1999.
Entender o Tomcat vai além de saber iniciar o servidor e fazer deploy de um .war. Conhecer sua arquitetura interna, os componentes que gerenciam o ciclo de vida de Servlets, como configurar corretamente um pool de conexões de banco de dados e como ler os logs para diagnosticar problemas — esse conhecimento é o que separa quem apenas usa o Tomcat de quem realmente o domina.
Neste guia você vai encontrar tudo que precisa para trabalhar bem com o Apache Tomcat: o que o diferencia de um servidor web comum como o Apache HTTP Server, como seus componentes internos (Catalina, Coyote, Jasper) funcionam juntos, o passo a passo de instalação em Windows e Linux, configurações iniciais de segurança e performance, integração com bancos de dados via pool de conexões, e como usar os logs para diagnosticar os problemas mais comuns. Cada seção traz ação prática, não apenas conceito.
O que é o Apache Tomcat e por que ele existe?
O Apache Tomcat é um servidor de aplicações web de código aberto que implementa as especificações Java Servlet e JavaServer Pages (JSP). Ele nasceu em 1999 quando a Apache Software Foundation adquiriu o código-fonte do projeto original da Sun Microsystems, e desde então evoluiu continuamente acompanhando as mudanças no ecossistema Java.
A distinção mais importante que qualquer desenvolvedor precisa entender desde o início: Tomcat não é a mesma coisa que o Apache HTTP Server, embora os dois compartilhem o nome “Apache” por pertencerem à mesma fundação.
Servidor web versus servidor de aplicação
O Apache HTTP Server é excelente no que faz: entregar arquivos estáticos (HTML, CSS, imagens, JavaScript) com extrema eficiência. Quando o navegador pede uma imagem ou um arquivo CSS, o Apache HTTP Server encontra o arquivo no disco e o serve — sem executar uma linha sequer de código de aplicação.
O Tomcat resolve um problema diferente. Quando a aplicação precisa processar uma solicitação dinamicamente — consultar um banco de dados, executar regras de negócio, gerar HTML baseado em dados em tempo real —, um servidor de arquivos estáticos não consegue fazer isso. O Tomcat atua como contêiner de Servlets e JSP, gerenciando o ciclo de vida completo desses componentes: inicialização, processamento de requisições e encerramento.
💡 Dica: O Tomcat consegue servir arquivos estáticos, mas essa não é sua especialidade. Em produção, muitas arquiteturas combinam Nginx ou Apache HTTP Server na frente (para arquivos estáticos e balanceamento de carga) com Tomcat atrás (para processar as requisições dinâmicas). Essa separação de responsabilidades extrai o melhor de cada ferramenta.
Por que o mercado consolida no Apache Tomcat
Três características explicam a dominância do Tomcat entre os servidores de aplicações Java:
- Leveza: ao contrário de servidores de aplicação Java EE completos como JBoss ou WebLogic, o Tomcat implementa apenas Servlets e JSP — o suficiente para a maioria das aplicações, sem o peso de especificações que raramente se usam
- Custo zero: distribuição gratuita com licença Apache License 2.0, sem royalties nem restrições de uso comercial
- Comunidade ativa: mais de duas décadas de desenvolvimento contínuo, documentação extensa, bugs corrigidos rapidamente e suporte disponível em múltiplos canais
A arquitetura interna que você precisa conhecer
Entender como o Tomcat organiza seus componentes internamente ajuda tanto a debugar problemas quanto a tomar decisões melhores de configuração.
Catalina: o coração do contêiner
Catalina é o componente central do Tomcat — o contêiner de Servlets que processa requisições HTTP e gerencia o ciclo de vida de todos os componentes da aplicação. Quando uma requisição chega ao Tomcat, é o Catalina que determina qual Servlet deve processá-la, instancia o Servlet se necessário, passa a requisição para ele e gerencia a resposta.
O Catalina também implementa o modelo de contexto que isola aplicações entre si. Cada aplicação web roda em seu próprio contexto, com seu próprio classloader, evitando que conflitos de dependências entre aplicações diferentes se propaguem.
Coyote: gerenciando a comunicação de rede
O Coyote é o conector responsável pela comunicação entre clientes externos e o contêiner Servlet. Ele gerencia os protocolos de rede que o Tomcat suporta — HTTP/1.1, HTTP/2 e AJP — traduzindo as requisições que chegam pela rede em objetos que o Catalina consegue processar, e fazendo o caminho inverso com as respostas.
A configuração do Coyote determina aspectos como a porta em que o servidor escuta, limites de conexões simultâneas, timeouts e configurações SSL/TLS para HTTPS. Esses parâmetros vivem no arquivo server.xml e impactam diretamente a performance e a segurança do servidor.
Jasper: compilando JSP em Servlets
O Jasper funciona como compilador JSP dentro do Tomcat. Quando uma página .jsp chega para processamento pela primeira vez, o Jasper a compila para código Java Servlet, que então passa pelo ciclo normal de compilação e execução da JVM. Em requisições subsequentes para a mesma página, o Jasper verifica se o arquivo JSP mudou desde a última compilação — se não mudou, reutiliza o Servlet já compilado.
Esse processo de compilação sob demanda é transparente para o desenvolvedor, mas tem implicação prática: a primeira requisição para qualquer página JSP não cacheada tem latência maior que as subsequentes. Em ambientes de produção, pré-compilar as JSPs antes de fazer deploy elimina esse problema.
Classloading: isolamento entre aplicações
O mecanismo de classloading do Tomcat gerencia como classes Java chegam à JVM dentro de um ambiente multi-aplicação. Cada aplicação web deployada no Tomcat recebe seu próprio classloader isolado, o que significa que uma aplicação não consegue acessar as classes de outra — mesmo que ambas estejam rodando no mesmo servidor ao mesmo tempo.
⚠️ Atenção: Conflitos de classloading são uma das causas mais comuns de comportamento inesperado em deployments Tomcat. Se a mesma biblioteca aparece tanto no diretório lib do Tomcat quanto no WEB-INF/lib da aplicação, o Tomcat precisa decidir qual versão usar — e a decisão nem sempre é a que você esperaria. Mantenha dependências compartilhadas no lib do Tomcat e dependências específicas da aplicação no WEB-INF/lib.
Security Manager e Web Applications
O Security Manager implementa políticas de controle de acesso a recursos sensíveis — arquivos do sistema, conexões de rede, propriedades do sistema — para código rodando dentro do Tomcat. Na maioria dos deployments modernos ele fica desabilitado por impactar performance, mas em ambientes multi-tenant onde múltiplas aplicações de origens diferentes compartilham o mesmo servidor, habilitá-lo oferece uma camada extra de proteção.
Cada aplicação web deployada no Tomcat representa uma unidade isolada com seu próprio contexto, configurações, recursos e classloader. Essa isolação permite que o mesmo servidor hospede múltiplas aplicações simultaneamente sem que elas interfiram umas nas outras.
Instalação passo a passo em Windows e Linux
Requisitos antes de instalar
O Tomcat exige Java Runtime Environment (JRE) ou Java Development Kit (JDK) instalado na máquina. Verifique a compatibilidade de versões: o Tomcat 10.x exige Java 11 ou superior; o Tomcat 9.x roda com Java 8 ou superior. Execute java -version no terminal para confirmar que o Java está instalado e qual versão está disponível.
O site oficial https://tomcat.apache.org sempre lista as versões estáveis disponíveis e os requisitos de cada uma. Baixe a versão correspondente ao seu ambiente — o pacote Core em formato .zip ou .tar.gz funciona em qualquer plataforma; o instalador .exe facilita a instalação como serviço no Windows.
Instalação no Windows
Usando o instalador .exe:
- Baixe o instalador Windows de
https://tomcat.apache.org/download-*x*.cgi - Execute o instalador como administrador e siga o assistente
- Escolha os componentes (Service Startup para rodar como serviço do Windows, Native para performance melhorada)
- Defina a porta HTTP (padrão: 8080), porta de shutdown (padrão: 8005) e porta HTTPS se necessário
- Informe o caminho do JDK quando solicitado
- Conclua a instalação; o Tomcat inicia automaticamente se você marcou a opção de serviço
Usando o pacote .zip:
- Extraia o
.zipem um diretório de sua escolha (ex:C:\tomcat) - Configure a variável de ambiente
CATALINA_HOMEapontando para esse diretório - Execute
bin\startup.batpara iniciar oubin\shutdown.batpara parar o servidor - Acesse
http://localhost:8080para confirmar que o servidor está rodando
Instalação no Linux
Via gerenciador de pacotes (Ubuntu/Debian):
sudo apt update
sudo apt install tomcat9 # Instala o Tomcat 9
sudo systemctl start tomcat9
sudo systemctl enable tomcat9 # Habilita início automático com o sistema
sudo systemctl status tomcat9 # Verifica se está rodandoVia pacote .tar.gz (qualquer distribuição):
# Baixe o Tomcat
wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.x/bin/apache-tomcat-10.1.x.tar.gz
# Extraia em /opt (diretório convencional para software de terceiros)
sudo tar xzf apache-tomcat-10.1.x.tar.gz -C /opt
sudo mv /opt/apache-tomcat-10.1.x /opt/tomcat
# Configure as variáveis de ambiente
echo 'export CATALINA_HOME=/opt/tomcat' >> ~/.bashrc
echo 'export PATH=$PATH:$CATALINA_HOME/bin' >> ~/.bashrc
source ~/.bashrc
# Inicie o servidor
$CATALINA_HOME/bin/startup.sh
# Verifique nos logs se iniciou sem erros
tail -f $CATALINA_HOME/logs/catalina.outConfigurações iniciais de segurança e performance
Altere as credenciais do Tomcat Manager imediatamente. O arquivo conf/tomcat-users.xml controla acesso à interface de gerenciamento web. O padrão de instalação frequentemente não configura nenhum usuário ou usa credenciais triviais. Adicione usuários com roles específicas:
<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="SuaSenhaForte123!" roles="manager-gui,admin-gui"/>
</tomcat-users>💡 Dica: Em servidores de produção, remova completamente as aplicações de gerenciamento (manager e host-manager) do diretório webapps se você não precisa delas. A interface de gerenciamento é um vetor de ataque frequente quando fica exposta com credenciais fracas ou padrão.
Configure a porta HTTP padrão (8080) para não ficar acessível diretamente da internet. Use Nginx ou Apache HTTP Server como proxy reverso na frente do Tomcat, redirecionando requisições externas da porta 80/443 para a porta 8080 internamente. Isso também facilita a configuração de SSL/TLS no proxy, que é mais simples de gerenciar do que diretamente no Tomcat.
Integração com banco de dados e Pool de conexões
Por que pool de conexões existe e por que importa
Abrir uma nova conexão com o banco de dados a cada requisição HTTP é caro — a operação envolve autenticação, negociação de protocolo e alocação de recursos tanto no cliente quanto no servidor de banco de dados. Em uma aplicação com dezenas de requisições por segundo, esse overhead acumula e degrada performance significativamente.
Pool de conexões resolve esse problema mantendo um conjunto de conexões já abertas e prontas para uso. Quando uma requisição precisa de acesso ao banco, ela pega uma conexão disponível do pool, usa-a, e a devolve ao pool ao terminar — sem fechar e reabrir a conexão física cada vez.
Configurando JNDI datasource no Apache Tomcat
O Tomcat suporta configuração de datasource via JNDI (Java Naming and Directory Interface), que permite que aplicações busquem a configuração de conexão pelo nome, sem precisar hardcodar parâmetros no código da aplicação.
No arquivo conf/context.xml (ou no META-INF/context.xml da aplicação), adicione o recurso:
<Context>
<Resource
name="jdbc/MeuBancoDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/meubanco"
username="usuario_app"
password="senha_segura"
maxTotal="20"
maxIdle="10"
minIdle="5"
maxWaitMillis="10000"
validationQuery="SELECT 1"
testOnBorrow="true"
testWhileIdle="true"
timeBetweenEvictionRunsMillis="60000"
/>
</Context>Cada parâmetro tem impacto direto no comportamento do pool:
- maxTotal: número máximo de conexões simultâneas no pool — defina com base na capacidade do servidor de banco de dados
- maxIdle: conexões que ficam abertas mesmo sem uso; manter algumas idle evita a latência de criar conexão nova em picos súbitos de tráfego
- minIdle: garante que pelo menos esse número de conexões esteja sempre disponível
- maxWaitMillis: tempo máximo que uma requisição espera por uma conexão disponível antes de lançar exceção
- validationQuery + testOnBorrow: verifica se a conexão ainda está válida antes de entregá-la para a aplicação — essencial para detectar conexões quebradas sem precisar reiniciar o servidor
Adicione o driver JDBC correspondente ao diretório lib do Tomcat. A aplicação então busca o datasource pelo nome JNDI:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/MeuBancoDB");
Connection conn = ds.getConnection();
// use a conexão...
conn.close(); // devolve ao pool, não fecha a conexão físicaSegurança: o que configurar antes de ir para produção
HTTPS com SSL/TLS
Servir tráfego HTTP não criptografado em produção expõe dados dos usuários. Para habilitar HTTPS diretamente no Tomcat, gere ou obtenha um certificado SSL e configure o conector no server.xml:
<Connector
port="8443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150"
SSLEnabled="true">
<SSLHostConfig>
<Certificate
certificateKeystoreFile="conf/seu-certificado.p12"
certificateKeystorePassword="senha_do_keystore"
type="RSA"/>
</SSLHostConfig>
</Connector>Em ambientes com proxy reverso (Nginx ou Apache HTTP Server na frente), configure o SSL no proxy e use HTTP puro entre o proxy e o Tomcat na rede interna — essa arquitetura simplifica gerenciamento de certificados e reduz overhead de criptografia no Tomcat.
Autenticação de usuários e controle de acesso
O Tomcat suporta múltiplos Realms para autenticação — mecanismos que definem onde e como verificar credenciais. O MemoryRealm lê usuários do tomcat-users.xml, adequado apenas para testes. Em produção, use JDBCRealm para autenticar contra um banco de dados ou JNDIRealm para integrar com LDAP/Active Directory corporativo.
Configure restrições de acesso no web.xml da aplicação usando <security-constraint> para definir quais URLs requerem autenticação e quais roles têm acesso:
<security-constraint>
<web-resource-collection>
<web-resource-name>Área Admin</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>Usando os logs para diagnosticar problemas
Os logs do Tomcat são a primeira parada quando algo não funciona como esperado. Saber onde encontrar cada tipo de informação economiza horas de troubleshooting.
Os principais arquivos de log
catalina.out — o log mais importante. Registra tudo que acontece no nível do servidor: inicialização, parada, deploy de aplicações, exceções não tratadas em Servlets, mensagens enviadas para System.out e System.err. Se o servidor não inicia, se uma aplicação falha ao fazer deploy, se uma exceção está quebrando requisições — a resposta está aqui.
access.log — registra cada requisição HTTP recebida pelo servidor em formato padrão (similar ao Combined Log Format do Apache). Útil para análise de tráfego, identificar endpoints lentos, detectar padrões de acesso suspeitos e calcular métricas de uso. O formato pode ser configurado no server.xml via AccessLogValve.
localhost.log e logs específicos por host — registram eventos específicos do host virtual padrão, incluindo erros de inicialização de contexto (quando uma aplicação específica falha ao iniciar) que às vezes não aparecem com detalhe suficiente no catalina.out.
Lendo o catalina.out para diagnosticar problemas comuns
Porta já em uso:
java.net.BindException: Address already in use: bind
Significa que outra aplicação está usando a porta configurada (8080 por padrão). Identifique o processo com lsof -i :8080 (Linux) ou netstat -ano | findstr :8080 (Windows) e encerre-o, ou altere a porta do Tomcat no server.xml.
OutOfMemoryError:
java.lang.OutOfMemoryError: Java heap space
O Tomcat está consumindo mais memória do que a JVM tem disponível. Aumente o heap configurando JAVA_OPTS no setenv.sh (Linux) ou setenv.bat (Windows):
export JAVA_OPTS="-Xms512m -Xmx2048m"
ClassNotFoundException ao iniciar aplicação:
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
O driver JDBC ou outra dependência está faltando. Verifique se o .jar correspondente está em WEB-INF/lib da aplicação ou em lib do Tomcat.
💡 Dica: Configure o nível de log de forma granular no conf/logging.properties. Para investigar um problema específico em um Servlet, aumente o nível de log apenas para o pacote relevante (com.suaempresa.app.level = FINE) em vez de ativar log verbose para todo o servidor — isso produz menos ruído e encontra o problema mais rápido.
Perguntas frequentes sobre Apache Tomcat
O Tomcat implementa apenas o subconjunto de especificações Jakarta EE relacionado a web — Servlets, JSP e WebSocket. Servidores Java EE completos como JBoss/WildFly, GlassFish e WebLogic implementam a especificação completa, incluindo EJB, JMS, JTA e outras tecnologias empresariais. Para a maioria das aplicações modernas que usam frameworks como Spring ou Quarkus para gerenciar injeção de dependência e transações, o Tomcat é suficiente e mais leve. Use servidores Java EE completos apenas quando você realmente precisa de funcionalidades específicas que eles oferecem e que o Tomcat não cobre.
Existem três formas principais. A mais simples é copiar o arquivo .war da aplicação para o diretório webapps do Tomcat — o servidor detecta automaticamente o novo arquivo e faz o deploy sem reiniciar. Alternativamente, use a interface web do Tomcat Manager (http://localhost:8080/manager) para fazer upload e deploy via navegador. Para ambientes automatizados, o Maven tem o plugin tomcat7-maven-plugin (compatível com versões mais recentes também) que faz deploy via linha de comando como parte do build.
Diretamente, rodar na porta 80 exige privilégios de root no Linux (portas abaixo de 1024 são restritas). A abordagem mais comum e recomendada em produção é manter o Tomcat na porta 8080 e usar Nginx ou Apache HTTP Server como proxy reverso na frente, escutando na porta 80 e encaminhando requisições para o Tomcat. Isso também facilita terminar SSL/TLS no proxy e servir arquivos estáticos sem envolver o Tomcat.
Verifique a compatibilidade com as especificações que sua aplicação usa. O Tomcat 10.x implementa Jakarta Servlet 6.0 (com o namespace jakarta.* em vez de javax.*), adequado para aplicações novas usando Spring 6+ ou Jakarta EE. O Tomcat 9.x implementa Java Servlet 4.0 com o namespace javax.* e é compatível com Spring 5 e versões anteriores. Se você está migrando de uma aplicação existente que usa javax.*, o Tomcat 9.x evita a necessidade de renomear imports; para projetos novos, o Tomcat 10.x com jakarta.* é a escolha mais alinhada com o ecossistema atual.
Configure o Nginx como proxy reverso adicionando um bloco location no arquivo de configuração do Nginx que encaminha requisições para o Tomcat:server {
listen 80;
server_name meusite.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Essa configuração faz com que o Nginx receba todas as requisições externas e as encaminhe para o Tomcat internamente, aproveitando o Nginx para servir arquivos estáticos com mais eficiência e terminar conexões SSL antes de chegarem ao Tomcat.
Conclusão
O Apache Tomcat acumulou mais de duas décadas de uso em produção por uma razão direta: ele resolve um problema específico — hospedar aplicações web Java com Servlets e JSP — de forma confiável, leve e sem custo de licença. Jenkins roda nele, Jira pode rodar nele, e incontáveis aplicações corporativas ao redor do mundo dependem dessa infraestrutura todos os dias.
Três pontos resumem o essencial deste guia. Primeiro, entender a arquitetura interna — Catalina processando requisições, Coyote gerenciando rede, Jasper compilando JSP — não é conhecimento de curiosidade: é o que permite configurar corretamente e diagnosticar problemas com precisão em vez de tentativa e erro. Segundo, segurança antes de ir para produção não é opcional: alterar credenciais padrão do Manager, configurar HTTPS e usar proxy reverso na frente do Tomcat são decisões que custam pouco para implementar e muito para ignorar. Terceiro, o pool de conexões configurado corretamente no context.xml é frequentemente a diferença entre uma aplicação que escala sob carga e uma que começa a acumular timeouts quando o tráfego cresce.
O Tomcat é uma ferramenta madura, bem documentada e com comunidade ativa que ainda responde a dúvidas em fóruns há décadas. Quem investe em entendê-lo fundo em vez de apenas “fazer funcionar” ganha uma infraestrutura confiável que sustenta aplicações Java por anos sem surpresas.
Se este guia ajudou você a entender o Tomcat além do básico de iniciar o servidor, compartilhe com o time de backend. O conhecimento de infraestrutura que fica concentrado em uma pessoa sempre vira gargalo quando ela tira férias.
Uma resposta