Servlets, JSP e MVC (Java Web clássico)¶
Antes de Spring, JSF e das APIs REST, a web em Java era feita com servlets e JSP. Entender essa base explica o que os frameworks fazem por baixo (Spring MVC, JSF e Jakarta EE usam servlets), e ainda é cobrado em entrevistas e em manutenção de legado. Veja os frameworks modernos em Spring e JSF, e o protocolo HTTP em Backend.
Java EE/Jakarta EE e os contêineres¶
Definição: contêiner de servlets
Servlet container (Tomcat, Jetty) é o servidor que hospeda aplicações web Java: recebe as requisições HTTP, cria e gerencia as servlets e devolve as respostas. Um servidor de aplicação (WildFly, WebLogic, WebSphere) inclui o contêiner de servlets e mais serviços Jakarta EE (EJB, JMS, transações).
- A aplicação é empacotada em um WAR (Web Application Archive) e implantada no contêiner. Estrutura típica: raiz com páginas (
.html,.jsp),WEB-INF/(inacessível pelo navegador),WEB-INF/web.xml(configuração),WEB-INF/classeseWEB-INF/lib(classes e JARs). - O contexto é o prefixo da URL (
/agenda); uma aplicação emROOTresponde na raiz (/). - O Tomcat é o mais comum; o Jetty é pequeno e embutível. Hoje é comum empacotar o contêiner dentro da aplicação (Spring Boot com Tomcat embutido). Detalhes de classloaders em Java avançado.
Servlets¶
Definição: servlet
Classe Java que atende requisições HTTP: lê os dados da requisição e escreve a resposta (HTML, JSON, imagem). Estende HttpServlet e
sobrescreve doGet, doPost etc.
@WebServlet("/adicionaContato") // mapeamento por anotação (Servlet 3+); antes era no web.xml
public class AdicionaContatoServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String nome = req.getParameter("nome"); // parâmetros vêm sempre como texto
String email = req.getParameter("email");
new ContatoDao().adiciona(new Contato(nome, email));
resp.sendRedirect("lista-contatos.jsp"); // redirect: novo GET (evita reenvio do POST)
}
}
- Ciclo de vida: o contêiner cria uma única instância da servlet (
init), usa-a para todas as requisições, em threads diferentes (service→doGet/doPost) e a destrói ao final (destroy). Por isso uma variável de instância é compartilhada entre todos os usuários: servlets devem ser thread-safe (sem estado mutável compartilhado). - Métodos HTTP:
GET,POST,PUT,DELETE,HEAD,OPTIONS...; formulários HTML4 só enviam GET e POST. - Converter parâmetros: tudo chega como
String; converta datas, números e trate erros de conversão. - Escopos de dados:
request(uma requisição),session(usuário),application/ServletContext(toda a aplicação);setAttribute/getAttribute. - Exceções: em vez de espalhar
try/catch, configure páginas de erro centralizadas (<error-page>noweb.xml).
JSP, EL e JSTL¶
Definição: JSP (JavaServer Pages)
Página HTML com trechos dinâmicos que o contêiner compila para uma servlet na primeira requisição. Resolve o incômodo de gerar HTML com
out.println dentro do Java.
- Scriptlets (
<% código Java %>) misturam Java e HTML: o problema que o JSP supostamente resolveria volta. Evite: use EL e taglibs, e mantenha a lógica na servlet (o JSP só apresenta). - EL (Expression Language):
${contato.nome},${param.idade},${sessionScope.usuario}: acessa propriedades de beans (via getters) e procura o atributo nos escopos (page,request,session,application). - JSTL (JSP Standard Tag Library):
c:forEach(itera coleção:items,var),c:if,c:choose,c:import(inclui cabeçalho/rodapé),c:url(monta URLs corretas com o contexto),fmt:formatDate/fmt:formatNumber(formatação). - Tagfiles: quando faltam tags, crie as suas em
.tag(por exemplo, "campo de data com calendário"), com atributos recebidos por EL, eliminando repetição. - Inclusões: diretiva
include(estática, em tempo de compilação) xjsp:include/c:import(dinâmica).
<%@ taglib uri="jakarta.tags.core" prefix="c" %>
<table>
<c:forEach var="contato" items="${contatos}">
<tr><td>${contato.nome}</td>
<td><c:if test="${not empty contato.email}"><a href="mailto:${contato.email}">${contato.email}</a></c:if></td></tr>
</c:forEach>
</table>
MVC com servlet controladora¶
Um JSP que cria ContatoDao e consulta o banco mistura responsabilidades. O padrão MVC separa Model (regras e dados), View (JSP) e Controller (servlet):
- A requisição chega à servlet, que executa a lógica e guarda o resultado na requisição (
req.setAttribute("contatos", lista)). - Ela encaminha (
RequestDispatcher.forward) ao JSP, que só exibe (EL + JSTL). O forward é interno ao servidor (a URL não muda); o redirect é uma nova requisição do navegador. - Coloque os JSPs em
WEB-INF/jsppara que não possam ser acessados diretamente pelo navegador.
Do if/else ao Front Controller e ao Command¶
Uma servlet com if (acao.equals("AdicionaContato")) ... else if ... cresce sem fim e é "propensa a erros". A solução evolui assim:
sequenceDiagram
participant N as Navegador
participant C as ControllerServlet (único ponto de entrada)
participant L as Lógica (Command)
participant J as JSP
N->>C: GET /mvc?logica=RemoveContato&id=5
C->>L: instancia a classe pelo nome (Class.forName) e chama executa()
L-->>C: devolve "/WEB-INF/jsp/lista.jsp"
C->>J: forward
J-->>N: HTML
- Cada ação vira uma classe que implementa uma interface (
LogicacomString executa(req, resp)): padrão Command. - Uma servlet controladora única (Front Controller) lê o parâmetro, instancia a lógica por reflexão e encaminha ao JSP que a lógica indicar.
- Isolar a criação de objetos por
Class.forNameé uma forma de Factory. Esse é exatamente o papel que Spring MVC (DispatcherServlet), Struts, VRaptor e JSF automatizam (Spring MVC).
Filtros¶
Definição: filtro (Filter)
Classe que intercepta requisições e respostas antes e depois da servlet/JSP, para tratar requisitos não funcionais transversais (logging/auditoria, autenticação, compressão, abrir e fechar a conexão com o banco por requisição), sem acoplar isso às servlets.
@WebFilter("/*")
public class TempoDeRequisicaoFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
long ini = System.currentTimeMillis();
chain.doFilter(req, resp); // passa adiante (próximo filtro ou a servlet)
System.out.println("levou " + (System.currentTimeMillis() - ini) + " ms");
}
}
Filtros formam uma cadeia (ordem definida no web.xml); são o antepassado dos interceptors do Spring e dos middlewares do Express (Node.js).
Autenticação: um filtro (ou interceptor) verifica a sessão e redireciona ao login (Segurança).
Recursos da Servlet API¶
init-paramecontext-paramnoweb.xml: parâmetros de configuração fora do código (usados por Spring e VRaptor).welcome-file-list: página aberta quando o cliente acessa um diretório.- Listeners:
ServletContextListenerexecuta código no início e fim da aplicação (inicializar cache, pool, configurações globais); também existem para sessão e atributos. - Sessão:
HttpSessionguarda o estado do usuário no servidor (identificada por cookieJSESSIONID); em cluster, exige replicação ou sessão externa.
Onde cada peça foi parar¶
| Peça clássica | Hoje |
|---|---|
| Servlet + Front Controller | DispatcherServlet (Spring MVC), controladores REST |
| JSP + JSTL | Thymeleaf, JSF/Facelets, front-end SPA (Angular) |
| Filtros | Filtros/interceptors do Spring, Spring Security |
web.xml |
Anotações e auto-configuração (Spring Boot) |
| JDBC + DAO | JPA/Spring Data (Acesso a dados) |
Para responder em entrevista¶
| Pergunta | Ideias para a resposta |
|---|---|
| "Ciclo de vida de uma servlet?" | init (uma vez), service/doGet/doPost por requisição (várias threads), destroy; uma instância só |
| "Por que uma servlet deve ser thread-safe?" | O contêiner usa uma única instância para todas as requisições; estado de instância é compartilhado |
"forward x redirect?" |
Forward é interno ao servidor (mesma requisição, URL não muda); redirect manda o navegador fazer outra requisição (evita reenvio de POST) |
| "O que é Front Controller?" | Ponto único de entrada que despacha para ações; base do Spring MVC |
| "Para que servem filtros?" | Preocupações transversais: log, autenticação, transação por requisição |
| "Por que evitar scriptlets?" | Misturam lógica e apresentação; use EL/JSTL e coloque a lógica na servlet/serviço |