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 comoctxebasePath, 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 deWEB-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-INFpara evitar acesso direto. - Use
forward(nãoredirect) para navegar entre páginas emWEB-INF.