Mecanismos de Navegação: Encaminhamento vs. Redirecionamento
No desenvolvimento de aplicações web com Java, o controle de fluxo entre diferentes recursos é fundamental. O Jakarta Servlet API oferece duas abordagens distintas para realizar transições de página: o encaminhamento de requisição (Request Forwarding) e o redirecionamento de resposta (Response Redirecting).
Encaminhamento de Requisição (Forward)
O encaminhamento é uma operação executada inteiramente no lado do servidor. O servidor atua como um entermediário, recebendo a solicitação e passando o controle para outro recurso interno sem notificar o navegador do cliente.
- Implementação: Utiliza a interface
RequestDispatcherobtida viaHttpServletRequest. - Ciclo de Vida: Envolve apenas uma requisição HTTP e um par de objetos
request/response. - Estado: Os atributos e parâmetros da requisição original são preservados e acessíveis pelo recurso de destino.
- Visibilidade: A URL na barra de endereços do navegador permanece inalterada.
- Segurança: Permite o acesso a recursos protegidos dentro do diretório
WEB-INF, sendo a única forma de renderizá-los diretamente. - Limitação: O destino deve residir estritamente dentro da mesma aplicação web.
package br.com.sistema.controllers;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/processar-pedido")
public class PedidoController extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Lógica de negócio e validação
req.setAttribute("mensagemStatus", "Pedido processado com sucesso.");
// Encaminhamento interno para um template JSP protegido
RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/views/confirmacao.jsp");
dispatcher.forward(req, resp);
}
}
Redirecionamento de Resposta (Redirect)
O redirecionamento é uma instrução dada ao cliente. O servidor responde com um código de status HTTP 302 (Found) e um cabeçalho Location, ordenando que o navegador faça uma nova requisição para a URL especificada.
- Implementação: Utiliza o método
sendRedirect(String location)doHttpServletResponse. - Ciclo de Vida: Gera pelo menos duas requisições HTTP independentes, criando novos objetos
requesteresponse. - Estado: Os dados da requisição original (attributes) são perdidos. Parâmetros de URL podem ser repassados manualmente.
- Visibilidade: A URL na barra de endereços do navegador é atualizada para o novo destino.
- Abrangência: Pode apontar para qualquer URL válida, incluindo domínios externos ou recursos estáticos.
- Limitação: Não consegue acessar recursos ocultos no diretório
WEB-INF, pois a requisição parte do navegador.
Tratamento de Codificação de Caracteres
Problemas de exibição de texto (conhecidos como mojibake) ocorrem fundamentalmente por discrepâncias entre a codificação utilizada para escrever os dados e a decodificação usada para lê-los, ou pelo uso de charsets que não suportam determinados glifos.
Configuração de Ambiente e Frontend
Para evitar inconsistências, a stack completa deve operar sob o padrão UTF-8:
- Documentos HTML: Declarar
<meta charset="UTF-8">no cabeçalho. - IDE e Compilador: Configurar o Global Encoding e o Project Encoding para UTF-8.
- Console do Servidor: Adicionar o argumento
-Dfile.encoding=UTF-8nas configurações da JVM do Tomcat para garantir que a saída padrão (stdout) processe caracteres acentuados corretamente.
Codificação em Requisições HTTP
- Método GET: Os parâmetros trafegam na URL. O Tomcat 10+ assume UTF-8 por padrão para decodificar a URI. Se o navegador codificar a URL em um padrão diferente (influenciado pelo charset da página HTML), ocorrerá corrupção de dados.
- Método POST: Os parâmetros trafegam no corpo da requisição. É obrigatório definir a codificação no servidor antes de qualquer chamada a
getParameter().
Codificação em Respostas HTTP
O servidor deve instruir explicitamente o navegador sobre qual charset utilizar para renderizar o payload. A abordagem mais robusta é configurar o cabeçalho Content-Type.
package br.com.sistema.controllers;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/cadastro-usuario")
public class UsuarioServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. Define a leitura do corpo da requisição como UTF-8
req.setCharacterEncoding("UTF-8");
// 2. Configura a resposta para informar o navegador sobre o charset
resp.setContentType("text/html; charset=UTF-8");
resp.setCharacterEncoding("UTF-8");
String nomeUsuario = req.getParameter("nome");
PrintWriter out = resp.getWriter();
out.println("");
out.println("<html><head><title>Perfil</title></head><body>");
out.println("<h1>Bem-vindo, " + nomeUsuario + "!</h1>");
out.println("</body></html>");
}
}
Resolução de Caminhos em Aplicações Web
A manipulação de rotas e recursos exige compreensão clara sobre como os caminhos são interpretados pelo servidor e pelo cliente.
Caminhos Relativos vs. Absolutos
- Relativos: Não iniciam com barra (
/). A resolução depende da URL atual do navegador. Utilizam./(diretório atual) ou../(diretório pai). São frágeis, pois quebram se a estrutura de URLs for alterada. - Absolutos: Iniciam com barra (
/). Apontam para uma raiz fixa, independentemente da localização atual do recurso.
Estratégias de Implementação de Caminhos
No Frontend (HTML/JSP):
O uso de caminhos absolutos no navegador exige a inclusão do contexto da aplicação (ex: /minha-loja/imagens/logo.png). Para evitar hardcoding, utiliza-se a tag base:
<base href="${pageContext.request.contextPath}/">
Isso transforma caminhos relativos em absolutos de forma dinâmica.
Em Redirecionamentos (Client-Side):
Como o redirecionamento é processado pelo navegador, a barra inicial (/) representa a raiz do servidor HTTP, não a raiz da aplicação. Portanto, o contexto deve ser concatenado explicitamente:
// Correto para redirecionamento
resp.sendRedirect(req.getContextPath() + "/painel-admin");
Em Encaminhamentos (Server-Side):
O encaminhamento ocorre internamente no contexto da aplicação web. A barra inicial (/) já representa a raiz do projeto deployado, dispensando o uso do context path:
// Correto para encaminhamento
req.getRequestDispatcher("/painel-admin").forward(req, resp);
Para unificar o comportamento de rotas, eliminar a necessidade de prefixos de contexto e simplificar a arquitetura de links, a prática recomendada em ambientes de produção é configurar o deploy da aplicação diretamente na raiz do servidor (Context Path: /).