Cómo acceder a recursos estáticos al asignar un servlet de controlador frontal global en /*
He asignado el despachador Spring MVC como un servlet de controlador frontal global en /*
.
<servlet>
<servlet-name>home</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Sin embargo, este mapeo detiene el acceso a archivos estáticos como CSS, JS, imágenes, etc., que se encuentran todos en la /res/
carpeta.
¿Cómo puedo acceder a ellos de todos modos?
Asigne el servlet del controlador a un url-pattern
tipo más específico /pages/*
, coloque el contenido estático en una carpeta específica /static
y cree una Filter
escucha /*
que continúe de forma transparente la cadena para cualquier contenido estático y envíe solicitudes al servlet del controlador para otro contenido.
En una palabra:
<filter>
<filter-name>filter</filter-name>
<filter-class>com.example.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>controller</servlet-name>
<servlet-class>com.example.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>controller</servlet-name>
<url-pattern>/pages/*</url-pattern>
</servlet-mapping>
con lo siguiente en los filtros doFilter()
:
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/static")) {
chain.doFilter(request, response); // Goes to default servlet.
} else {
request.getRequestDispatcher("/pages" + path).forward(request, response);
}
No, esto no termina /pages
en la barra de direcciones del navegador. Es totalmente transparente. Si es necesario, puede fabricar "/static"
y/o "/pages"
modificar init-param
el filtro.
Con Spring 3.0.4.RELEASE y superior puedes usar
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
Como se ve en Spring Reference .
Lo que haces es agregar un archivo de bienvenida en tu web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
Y luego agregue esto a sus asignaciones de servlet para que cuando alguien vaya a la raíz de su aplicación, sea enviado a index.html internamente y luego la asignación lo enviará internamente al servlet al que lo asigna.
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/main</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>MainActions</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
Resultado final: visita /Aplicación, pero se le presenta el servlet /Aplicación/MainActions sin interrumpir ninguna otra solicitud raíz.
¿Consíguelo? Por lo tanto, su aplicación todavía se encuentra en una URL secundaria, pero se presenta automáticamente cuando el usuario accede a la raíz de su sitio. Esto le permite tener /images/bob.img todavía en el lugar habitual, pero '/' es su aplicación.
Si usa Tomcat, puede asignar recursos al servlet predeterminado:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
y acceda a sus recursos con la URL http://{context path}/static/res/...
También funciona con Jetty, no estoy seguro acerca de otros contenedores de servlets.
Servir contenido estático con el sufijo apropiado en múltiples definiciones de mapeo de servlets resolvió el problema de seguridad que se menciona en uno de los comentarios de una de las respuestas publicadas. Citado a continuación:
Este era un agujero de seguridad en Tomcat (se puede acceder a los contenidos WEB-INF y META-INF de esta manera) y se solucionó en 7.0.4 (y también se trasladará a 5.xy 6.x). – BalusC el 2 de noviembre, 2010 en el 02:44
lo cual me ayudó mucho. Y así es como lo resolví:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>