Navegação, Codificação de Caracteres e Resolução de Caminhos em Aplicações Servlet

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 RequestDispatcher obtida via HttpServletRequest.
  • 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) do HttpServletResponse.
  • Ciclo de Vida: Gera pelo menos duas requisições HTTP independentes, criando novos objetos request e response.
  • 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-8 nas 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: /).

Tags: java servlet Jakarta EE HTTP utf-8

Publicado em 7-4 19:52