tutorial mvc framework español edicion cuarta books arquitectura accion spring configuration spring-mvc

framework - spring mvc 4 tutorial español



¿Se puede configurar SpringMVC para procesar todas las solicitudes, pero excluir directorios de contenido estático? (13)

Si mapeo mi aplicación de primavera para procesar todas las solicitudes entrantes (''/ *''), las solicitudes de contenido estático devuelven 404. Por ejemplo, una solicitud para "myhost.com/css/global.css" devolvería un 404, aunque el recurso existe cuando Spring intercepta la solicitud.

La alternativa es asignar SpringMVC a un subdirectorio (por ejemplo ''/ home / ''), pero en este caso, debe pasar este directorio en todos los enlaces dentro de la aplicación. ¿Hay alguna forma de asignar SpringMVC a ''/ '' y excluir del procesamiento un conjunto de directorios?

Mi configuración actual de web.xml es:

<servlet> <servlet-name>springApp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springApp</servlet-name> <url-pattern>/home/*</url-pattern> </servlet-mapping>

Idealmente, me gustaría que el mapeo sea algo así como lo siguiente:

<servlet-mapping> <servlet-name>springApp</servlet-name> <url-pattern>/*</url-pattern> <exclude>/css/*,/js/*</exclude> </servlet-mapping>

¿Es posible este tipo de cosas?


¿Qué estás usando para servir tus imágenes estáticas? Si es Apache, puede configurar Apache para que no pase las solicitudes de css / js a su servidor de aplicaciones.

Si está utilizando Tomcat, pondría algo como esto en su httpd.conf:

JkUnMount /*.css webapp

Donde ''webapp'' es la entrada de tus workers.properties.

Lo siento, no puedo darte una solución pura de Spring, pero así es como lo hago.


¿Tiene una (s) extensión (es) consistente (s) para las solicitudes que quiere que el despachador de Spring procese (creo que la mayoría de los ejemplos de Spring usan un * .htm)? En ese caso, podría mapear a las extensiones que desea procesar, que omitirían sus archivos css y js.

De lo contrario, estaría de acuerdo con Nalandial, el enfoque de filtro es probablemente el mejor trabajo en este momento.


En mi caso, todo estaba bien. Pero tengo un problema en un controlador

ese era mi problema @RequestMapping (method = RequestMethod.GET)

y cambio para esto:

@RequestMapping(value = "/usuario", method = RequestMethod.GET)

y funciona

busque un controlador que tenga mal @RequestMappgin y cambie.


Es más UrlRewriteFilter usar UrlRewriteFilter para redirigir la solicitud a su servlet, aquí un ejemplo de urlrewrite.xml

<urlrewrite> <rule> <from>^/img/(.*)$</from> <to>/img/$1</to> </rule> <rule> <from>^/js/(.*)$</from> <to>/js/$1</to> </rule> <rule> <from>^/css/(.*)$</from> <to>/css/$1</to> </rule> <rule> <from>^/(.*)$</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/(.*)$</from> <to>/$1</to> </outbound-rule> </urlrewrite>

NOTAS:

  • Es importante que la última <rule> esté en la parte inferior para que img, js, css se atrapen primero
  • La <outbound-rule> es opcional y es solo para hacer que la existente
    <c:url value="/app/some" /> render /some lugar de /app/some

Generalmente, los grandes sitios web prefieren usar otro servidor solo para manejar contenido estático. Las solicitudes de contenido estático van a un servidor y la dinámica va a otro (con la primavera, en este caso).

En muchos casos, servidor Nginx (http://nginx.com/), un servidor reciente y muy rápido.

Pero esto no es trivial de hacer. Muchas configuraciones


La forma más sencilla para mí (si usa una versión de Spring lo suficientemente avanzada) es

<mvc:resources mapping="/**/*.js" location="/"/> <mvc:resources mapping="/**/*.css" location="/"/> ...


Lo solucioné al servir contenido estático a través del servlet ''predeterminado'', que solo sirve el contenido para el cliente. Entonces mi web.xml se ve así:

<servlet> <servlet-name>MyApp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyApp</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The ''dynamic'' content --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <!-- The ''static'' content -->

Espero que esto ayude.


Si está utilizando Spring 3.0.4 y superior, debe usar la solución provista por atrain

De lo contrario, puedes hacer esto simple :

quizás tengas la siguiente estructura de directorio estático que deseas servir:

WebContent | WEB-INF | public | css | js | img

Los proyectos web dinámicos de Eclipse generan de forma predeterminada la estructura siguiente: WebContent/WEB-INF . Mueva la carpeta public de su directorio WEB-INF al directorio de WebContent .

Del lado del cliente

remita sus archivos estáticos de la siguiente manera:

<link rel="stylesheet" type="text/css" href="public/css/mystyles.css">

Aquí está mi reference.


Si quieres hacer esto solo con Spring, es posible pero un poco desordenado:

  1. Necesitará utilizar un SimpleUrlHandlerMapping para el cual puede especificar explícitamente patrones de URL que se deben mapear a los controladores O extenderlos para admitir URL "ignorar" como "css / **".
  2. Tendrá que escribir su propia implementación de HttpRequestHandler que básicamente consistiría en la llamada "getServletContext (). GetRequestDsipatcher (). Include ()" para devolver el recurso solicitado tal como está.
  3. Deberá registrar ese controlador como predeterminadoHandler para el SimpleUrlHandlerMapping anterior.

Una vez hecho todo esto, todas las solicitudes que no se pueden asignar a sus controladores se enviarán a su HttpRequestHandler y se servirán "tal cual".


Tengo el mismo problema y así es como lo resolví:

Lo siguiente fue agregado al archivo web.xml:

<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> <url-pattern>*.css</url-pattern> <url-pattern>*.ico</url-pattern> <url-pattern>*.png</url-pattern> <url-pattern>*.jpg</url-pattern> <url-pattern>*.htc</url-pattern> <url-pattern>*.gif</url-pattern> <url-pattern>*.html</url-pattern> <url-pattern>*.htm</url-pattern> </servlet-mapping>

Se agregó lo siguiente al archivo de definición de bean servlet spring3 MVC (como applicationContext.xml, el archivo que está configurado en web.xml como contextConfigLocation):

<mvc:annotation-driven /> <mvc:default-servlet-handler />


Una forma de hacerlo sería con filtros. Tendría que escribir un poco de código personalizado, pero no está mal. Aquí hay un ejemplo si no desea pasar archivos * .css o * .js a su servlet Spring:

web.xml:

<filter-mapping> <filter-name>fileTypeFilter</filter-name> <filter-class>foo.FileTypeFilter</filter-class> <url-pattern>/*</url-pattern> </filter-mapping>

Clase de Java:

public class FileTypeFilter implements Filter { public void init(FilterConfig conf) { // init logic here } public void destroy() { // release resources here } public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { if(shouldExclude(req)) { chain.doFilter(req, res); //some logic so the request doesnt go to the servlet //maybe you could just forward //the request directly to the file getting accessed. not sure if that would work } //file should be passed to the servlet; you can do some logic here //if you want } private boolean shouldExclude(ServletRequest req) { if(req instanceof HttpServletRequest) { HttpServletRequest hreq = (HttpServletRequest) req; return (hreq.getRequestURI().endsWith(".css") || hreq.getRequestURI().endsWith(".js")); } return false; } }

No lo he probado, pero creo que funcionará.

EDITAR : no hay ninguna funcionalidad de exclusión en la especificación del servlet. No creo que haya una buena manera de hacerlo en Spring, pero básicamente logra lo mismo en tu publicación.

EDIT 2 : Si desea poder cambiar fácilmente lo que se filtra, puede usar Spring para inyectar algo en el filtro en tiempo de ejecución.

EDIT 3 : Me acabo de dar cuenta de que si reenvía directamente al archivo, hará el filtro nuevamente y quedará atrapado en un ciclo infinito. Puede haber otra forma de hacer esto con filtros, pero honestamente no estoy seguro de qué se trata.


Utilizo la ruta de URL virtual para recuperar el recurso que necesito. Normalmente utilizo Spring MVC, por lo que no pude tener javascripts y css en la carpeta / WEB-INF / views. Se me ocurrió este servlet personalizado para SÓLO permitir el acceso a archivos .js y .css en la carpeta / WEB-INF / views. En su caso, si mueve la carpeta / css y / js a una carpeta principal como / resource, entonces mi solución se aplicará a usted.

Puede cambiar la url String = "YOUR_RESOURCE_FOLDER"

Por ejemplo, la ruta virtual puede ser algo así como http://www.mysite.com/resources/path/path/app.js

Eso se asignará a mi /WEB-INF/views/path/path/app.js

web.xml

<servlet> <servlet-name>ResourceDispatcherServlet</servlet-name> <servlet-class>mywebapp.web.ResourceDispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ResourceDispatcherServlet</servlet-name> <url-pattern>/resource/*</url-pattern> </servlet-mapping>

servlet

public class ResourceDispatcherServlet extends HttpServlet { public void init() throws ServletException { } public void doGet(HttpServletRequest req, HttpServletResponse rsp) throws ServletException, IOException { String servletPath = req.getServletPath(); // /resource String pathInfo = req.getPathInfo(); // /path/path/app.js String url = "/WEB-INF/views" + pathInfo; String lastPath = StringUtil.substringAfterLast(pathInfo, "/"); String extension = StringUtil.substringAfterLast(lastPath, "."); try { RequestDispatcher dispatcher = null; if (!StringUtil.isEmpty(extension) && ("js".equals(extension) || "css".equals(extension))) { dispatcher = req.getRequestDispatcher(url); } if (dispatcher != null) { dispatcher.include(req, rsp); } else { rsp.sendError(404); } } catch (Exception e) { if (!rsp.isCommitted()) { rsp.sendError(500); } } } }


NOTA: esta respuesta se aplica a Spring 3.0.4+ SOLAMENTE

(Por cierto, esta pregunta también se ha tratado aquí: Spring que brinda contenido estático con mvc: recursos, xsd no válido )

Consulte el proyecto Spring mvc-showcase en el repositorio de muestras de subversión Spring. Muestra exactamente lo que desea hacer, a saber, que puede delinear recursos estáticos que no serán procesados ​​por el DisapatcherServlet. Ver archivo /mvc-showcase/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml . Aquí hay un fragmento de cómo manejo estas exclusiones, donde JS, CSS e imágenes se encuentran en la raíz del contexto de la aplicación (con el espacio de nombres MVC asignado a mvc :

<!-- resources exclusions from servlet mapping --> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="/images/**" location="/images/" /> <mvc:resources mapping="/js/**" location="/js/" />