Resolução de erro 404 ao incluir arquivos JSP em aplicações Spring MVC

Em projetos Spring MVC, é comum organizar bibliotecas de tags e scripts compartilhados em arquivos JSP separados para reutilização. No entanto, ao tentar incluí-los via <%@ include %> ou <c:import>, pode ocorrer um erro 404 — mesmo que os caminhos estejam corretos.

Estrutura típica do projeto

Suponha a seguinte organização:

  • /WEB-INF/common/taglibs.jsp — define variáveis como ctx e basePath, além de importar taglibs JSTL e Spring.
  • /WEB-INF/common/jslibs.jsp — carrega scripts JavaScript comuns, utilizando ${basePath}.
  • /WEB-INF/front/user/login.jsp — página principle que tenta incluir os dois acima.

Configuração do Spring MVC

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="prefix" value="/WEB-INF/"/>
    <property name="suffix" value=".jsp"/>
</bean>

Problema raiz

O diretório WEB-INF é protegido por padrão — recursos ali contidos não são acessíveis diretamente via URL. Isso significa que:

  • <%@ include file="..." %> funciona, pois é uma inclusão no tempo de compilação (server-side).
  • <c:import url="..." /> falha se o recurso estiver dentro de WEB-INF, pois tenta acessá-lo via requisição HTTP.

Solução recomendada

Utilize inclusão estática com <%@ include %> para garantir que as variáveis definidas nos arquvios incluídos estejam disponíveis no escopo da página principal:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ include file="/WEB-INF/common/taglibs.jsp" %>
<%@ include file="/WEB-INF/common/jslibs.jsp" %>

<html>
<head>
    <title>Login</title>
    <base href="${basePath}">
</head>
<body>
    <script>console.log("Contexto: " + ctx);</script>
</body>
</html>

Alternativa com Forward Controller

Se for necessário usar <c:import> (por exemplo, em templates dinâmicos), crie um controller dedicado para servir esses fragmentos:

@Controller
public class FragmentController {

    @GetMapping("/fragments/{name}")
    public String serveFragment(@PathVariable String name, Model model) {
        return "common/" + name; // resolve para /WEB-INF/common/{name}.jsp
    }
}

Então, na JSP:

<c:import url="/fragments/taglibs" />

Regras importnates

  • Arquivos CSS, JS e imagens devem ficar fora de WEB-INF — normalmente em /static/ ou /resources/.
  • Páginas JSP podem (e devem) ficar dentro de WEB-INF para evitar acesso direto.
  • Use forward (não redirect) para navegar entre páginas em WEB-INF.

Tags: SpringMVC jsp jstl web-inf cimport

Publicado em 9-29 09:48