El navegador no puede acceder/encontrar recursos relativos como CSS, imágenes y enlaces cuando llama a un servlet que reenvía a un JSP
Tengo problemas para cargar CSS e imágenes y crear enlaces a otras páginas cuando tengo un servlet reenviado a un JSP. Específicamente, cuando configuro mi <welcome-file>
en index.jsp
, el CSS se carga y se muestran mis imágenes. Sin embargo, si configuro mi <welcome-file>
control HomeServlet
de reenvío en index.jsp
, el CSS no se aplica y mis imágenes no se muestran.
Mi archivo CSS está en formato web/styles/default.css
.
Mis imágenes están en web/images/
.
Estoy vinculando a mi CSS así:
<link href="styles/default.css" rel="stylesheet" type="text/css" />
Estoy mostrando mis imágenes de la siguiente manera:
<img src="images/image1.png" alt="Image1" />
¿Cómo se produce este problema y cómo puedo solucionarlo?
Actualización 1 : agregué la estructura de la aplicación, así como otra información que podría ayudar.
El header.jsp
archivo es el archivo que contiene la etiqueta de enlace para el CSS. El HomeServlet
está configurado como mi welcome-file
en web.xml
:
<welcome-file-list>
<welcome-file>HomeServlet</welcome-file>
</welcome-file-list>
El servlet se declara y asigna de la siguiente manera en web.xml
:
<servlet>
<servlet-name>HomeServlet</servlet-name>
<servlet-class>com.brianblog.frontend.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Actualización 2 : finalmente encontré el problema: mi servlet estaba asignado incorrectamente. Aparentemente, cuando se configura un Servlet como suyo, <welcome-file>
no puede tener un patrón de URL de /
, lo cual me parece un poco extraño, porque ¿no representaría eso el directorio raíz del sitio?
El nuevo mapeo es el siguiente:
<servlet-mapping>
<servlet-name>HomeServlet</servlet-name>
<url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
Todas las URL relativas en la página HTML generada por el archivo JSP son relativas a la URL de solicitud actual (la URL como se ve en la barra de direcciones del navegador) y no a la ubicación del archivo JSP en el lado del servidor como parece esperarse. Es concretamente el navegador web quien tiene que descargar esos recursos individualmente por URL, no el servidor web quien tiene que incluirlos desde el disco de alguna manera.
Además de cambiar las URL relativas para que sean relativas a la URL del servlet en lugar de a la ubicación del archivo JSP, otra forma de solucionar este problema es hacerlas relativas a la raíz del dominio (es decir, comenzar con a /
). De esta manera, no necesita preocuparse por cambiar las rutas relativas una vez más cuando cambia la URL del servlet.
<head>
<link rel="stylesheet" href="/context/css/default.css" />
<script src="/context/js/default.js"></script>
</head>
<body>
<img src="/context/img/logo.png" />
<a href="/context/page.jsp">link</a>
<form action="/context/servlet"><input type="submit" /></form>
</body>
Sin embargo, probablemente no desee codificar la ruta de contexto. Muy razonable. Puede obtener la ruta de contexto en EL mediante ${pageContext.request.contextPath}
.
<head>
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/default.css" />
<script src="${pageContext.request.contextPath}/js/default.js"></script>
</head>
<body>
<img src="${pageContext.request.contextPath}/img/logo.png" />
<a href="${pageContext.request.contextPath}/page.jsp">link</a>
<form action="${pageContext.request.contextPath}/servlet"><input type="submit" /></form>
</body>
(que se puede acortar <c:set var="root" value="${pageContext.request.contextPath}" />
y utilizar fácilmente como ${root}
en otros lugares)
O, si no temes el XML ilegible y el resaltado de sintaxis XML roto, usa JSTL <c:url>
:
<head>
<link rel="stylesheet" href="<c:url value="/css/default.css" />" />
<script src="<c:url value="/js/default.js" />"></script>
</head>
<body>
<img src="<c:url value="/img/logo.png" />" />
<a href="<c:url value="/page.jsp" />">link</a>
<form action="<c:url value="/servlet" />"><input type="submit" /></form>
</body>
De cualquier manera, esto es bastante engorroso si tienes muchas URL relativas. Para eso puedes usar la <base>
etiqueta. Todas las URL relativas se convertirán instantáneamente en relativas a ella. Sin embargo, debe comenzar con el esquema ( http://
, https://
, etc.). No existe una forma sencilla de obtener la ruta del contexto base en EL simple, por lo que necesitamos un poco de ayuda de JSTL aquí.
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="uri" value="${req.requestURI}" />
<c:set var="url">${req.requestURL}</c:set>
...
<head>
<base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
<link rel="stylesheet" href="css/default.css" />
<script src="js/default.js"></script>
</head>
<body>
<img src="img/logo.png" />
<a href="page.jsp">link</a>
<form action="servlet"><input type="submit" /></form>
</body>
Esto a su vez tiene (de nuevo) algunas salvedades. ¡ Los anclajes (las #identifier
URL) también serán relativos a la ruta base! En su lugar, le gustaría hacerlo relativo a la URL de solicitud (URI). Entonces, cambia como
<a href="#identifier">jump</a>
a
<a href="${uri}#identifier">jump</a>
Cada forma tiene sus pros y sus contras. Depende de usted cuál elegir. Al menos ahora deberías entender cómo se produce este problema y cómo solucionarlo :)
Ver también:
- ¿Se recomienda utilizar la
<base>
etiqueta html?
Me enfrenté a un problema similar con la aplicación Spring MVC. Usé < mvc:resources >
la etiqueta para resolver este problema.
Encuentre el siguiente enlace con más detalles.
http://www.mkyong.com/spring-mvc/spring-mvc-how-to-include-js-or-css-files-in-a-jsp-page/
Debe analizar la salida HTML real para obtener la pista.
Al dar la ruta de esta manera significa "desde la ubicación actual", por otro lado, si comienza con a, /
eso significaría "desde el contexto".
Puedes probar este también. Porque esto funcionó para mí y es simple.
<style>
<%@ include file="/css/style.css" %>
</style>