El navegador no puede acceder/encontrar recursos relativos como CSS, imágenes y enlaces cuando llama a un servlet que lo reenvía a un JSP
image servlets (7)
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>
en HomeServlet
que reenvía el control a index.jsp
, el CSS no se aplica y mis imágenes no se muestran.
Mi archivo CSS está en web/styles/default.css
.
Mis imágenes están en web/images/
.
Me estoy vinculando a mi CSS de esta manera:
<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 causa este problema y cómo puedo resolverlo?
Actualización 1 : He agregado la estructura de la aplicación, así como otra información que podría ayudar.
El archivo header.jsp
es el archivo que contiene la etiqueta de enlace para el CSS. 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 mapea como sigue 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 fue mapeado incorrectamente. Aparentemente, al configurar un Servlet como su <welcome-file>
no puede tener un patrón de URL de /
, lo que me parece un poco extraño, porque ¿eso no significaría 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>
Debe analizar la salida de HTML real, para la sugerencia.
Al dar el camino de esta manera significa "desde la ubicación actual", por otro lado, si comienza con un /
que significa "del contexto".
En cuanto a su actualización, estaba confundido por el razonamiento detrás de. Profundicé un poco más y encontré esta gema:
- yoursite.com se convierte en yoursite.com/
- yoursite.com/ es un directorio, por lo que la lista de archivos de bienvenida se escanea
- yoursite.com/CMS es el primer archivo de bienvenida ("CMS" en la lista de archivos de bienvenida), y hay una asignación de / CMS al servlet MyCMS, de modo que se accede al servlet.
Fuente: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage
Entonces, el mapeo tiene sentido.
¡Y ahora se puede usar libremente $ {pageContext.request.contextPath} / path / as src / href para enlaces relativos!
Me enfrenté a un problema similar con la aplicación Spring MVC. < mvc:resources >
etiqueta < mvc:resources >
para resolver este problema.
Por favor 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/
Si está utilizando Spring MVC, necesita declarar el servlet de acción predeterminado para los contenidos estáticos. Agregue las siguientes entradas en spring-action-servlet.xml. Funcionó para mí
NOTA: mantenga todos los contenidos estáticos fuera de WEB-INF.
<!-- Enable annotation-based controllers using @Controller annotations -->
<bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="0" />
</bean>
<bean id="controllerClassNameHandlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="order" value="1" />
</bean>
<bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
Su página de bienvenida está configurada como ese servlet. Por lo tanto, todas las CSS, la ruta de las imágenes se debe dar en relación con ese servlet DIR. que es una mala idea! ¿Por qué necesita el servlet como página de inicio? establecer .jsp como página de índice y redirigir a cualquier página desde allí?
¿Estás tratando de poblar cualquier campo de db? ¿Es por eso que estás usando servlet?
Todas las URL relativas en la página HTML generadas 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 servidor como parece esperar. Se trata del navegador web que tiene que descargar esos recursos individualmente por URL, no el servidor web que debe incluirlos en el disco de alguna manera.
Además de cambiar las direcciones URL relativas para que sean relativas a la URL del servlet en lugar de 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 forma, no tendrá que preocuparse por cambiar las rutas relativas una vez más cuando cambie 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 le gustaría no codificar la ruta de contexto. Muy razonable. Puede obtener la ruta de contexto en EL por ${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 fácilmente por <c:set var="root" value="${pageContext.request.contextPath}" />
y se usa como ${root}
otro lugar)
O bien, si no teme que XML ilegible y el resaltado de sintaxis XML rotos, use 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 a su vez es bastante engorroso si tiene muchas URL relativas. Para eso puedes usar la etiqueta <base>
. Todas las URL relativas se volverán instantáneamente relativas a ella. Sin embargo, debe comenzar con el esquema ( http://
, https://
, etc.). No existe una forma clara de obtener la ruta de contexto base en EL simple, por lo que necesitamos una pequeña 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 tiene a su vez (nuevamente) algunas advertencias. Anclas (las #identifier
URL del #identifier
) también serán relativas a la ruta base. En su lugar, le gustaría hacerlo en relación con la URL de solicitud (URI). Entonces, cambie como
<a href="#identifier">jump</a>
a
<a href="${uri}#identifier">jump</a>
Cada forma tiene sus propios pros y contras. Depende de usted elegir. Al menos, ahora debes entender cómo se causa este problema y cómo resolverlo :)
Ver también:
respuesta corta - agregue la siguiente línea en el jsp que definirá la base
base href = "/ {raíz de su aplicación} /"