如何在全局前端控制器servlet上映射/ *时访问静态资源
我将Spring MVC调度器映射为/*
上的全局前端控制器servlet。
<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>
但是,这个映射会停止访问静态文件,如CSS,JS,图像等,这些都在/res/
文件夹中。
我怎样才能访问它们呢?
我也遇到过这个问题,从来没有find一个很好的解决scheme。 我结束了在URL层次结构中更高一级的servlet映射:
<servlet-mapping> <servlet-name>home</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>
现在,基本上下文(和/ res目录下)中的所有内容都可以由容器提供。
将控制器servlet映射到像/pages/*
这样更具体的url-pattern
,将静态内容放在特定的文件夹(如/static
并创build一个Filter
listening on /*
,它透明地继续链接任何静态内容,并将请求发送到控制器servlet用于其他内容。
简而言之:
<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>
在filter的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); }
不,这不会以浏览器地址栏中的/pages
结束。 这是完全透明的。 你可以根据需要使"/static"
和/或"/pages"
的filter的init-param
。
使用Spring 3.0.4.RELEASE和更高版本可以使用
<mvc:resources mapping="/resources/**" location="/public-resources/"/>
正如在Spring Reference中看到的那样。
如果您使用Tomcat,则可以将资源映射到默认的servlet:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>
并通过url http:// {context path} / static / res /访问您的资源…
也适用于Jetty,不知道其他的servlet容器。
你所做的是在你的web.xml中添加一个欢迎文件
<welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list>
然后将其添加到您的servlet映射中,以便当有人访问您的应用程序的根目录时,它们会在内部发送到index.html,然后映射将在内部将它们发送到您映射到的servlet
<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>
最终结果:您访问/应用程序,但是您会看到/ Application / MainActions servlet,而不会中断任何其他根请求。
得到它? 所以你的应用程序仍然位于一个子url,但当用户转到你的网站的根目录时会自动呈现。 这可以让你有http://img.dovov.combob.img仍然去正常的地方,但'/'是你的应用程序。;
在多个servlet映射定义中使用适当的后缀来提供静态内容解决了所发布答案之一中的一个注释中提到的安全问题。 引用如下:
这是Tomcat中的一个安全漏洞(WEB-INF和META-INF的内容可以通过这种方式访问),并且已经在7.0.4中修复了(同时也将移植到5.x和6.x中)。 – – BalusC 10年10月2日在22:44
这帮助了我很多。 这是我如何解决它:
<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>
从3.0.4开始,您应该能够像mvc:default-servlet-handler
一样使用mvc:resources
,就像在spring文档中描述的一样。
App Engine中的“静态”文件不能直接通过您的应用访问。 您需要上传两次,或者自己提供静态文件,而不是使用静态处理程序。
碰撞的原因似乎是因为默认情况下,上下文根“/”由org.apache.catalina.servlets.DefaultServlet处理。 这个servlet旨在处理对静态资源的请求。
如果您决定用自己的servlet阻止它,为了处理dynamic请求,顶层servlet还必须执行由catalina原始的“DefaultServlet”处理程序完成的任何任务。
如果你仔细阅读tomcat文档,他们提到True Apache(httpd)比Apache Tomcat更好地处理静态内容,因为它的目的就是为了实现这一点。 我的猜测是因为Tomcat默认使用org.apache.catalina.servlets.DefaultServlet来处理静态请求。 由于它全部包装在JVM中,并且Tomcat旨在作为Servlet / JSP容器,所以它们可能不会将该类编写为超优化的静态内容处理程序。 在那。 它完成了工作。 够好了。
但是,这是处理静态内容的东西,它的生活在“/”。 所以,如果你把任何东西放在那里,那东西不处理静态请求,WHOOPS,那么你的静态资源。
我一直在寻找同样的答案,我得到的答案是“如果你不想这样做,不要这样做”。
长话短说,你的configuration是取代了默认的静态资源处理程序,而不是静态的资源处理程序。 你需要尝试一个不同的configuration来获得你正在寻找的结果(我也是如此)。
处理这个问题的最好方法是使用某种URL重写。 通过这种方式,您可以拥有干净的宁静url,而不需要任何扩展名,例如abc.com/welcom/register而不是abc.com/welcome/resister.html
我使用Tuckey的URL很酷。
它有关于如何设置您的Web应用程序的说明。我已经使用我的Spring MVC Web应用程序进行了设置。 当然,一切都很好,直到我想使用注释Spring @ 3validation像@Email
或@Null
域对象。
当我添加Spring mvc指令时:
< mvc:annotation-driven /> < mvc:default-servlet-handler />
它打破了良好的Tuckey代码。 显然, < mvc:default-servlet-handler />
取代了Tuckey,我仍然试图解决这个问题。
将您不想触发servlet处理的文件夹添加到appengine-web.xml文件的<static-files>
部分。
我只是这样做,看起来事情开始工作好了。 这是我的结构:
/
/pages/<.jsp文件>
/ CSS
我在<static-files>
部分添加了“/ pages / **”和“/ css / **”,现在我可以从servlet doGet内部转发到.jsp文件,而不会导致无限循环。
尝试filter的方法没有成功之后(它由于某种原因没有进入doFilter()函数)我改变了我的设置了一下,发现一个非常简单的解决scheme的根服务问题:
我现在只听专用的语言前缀“EN”,“EN / *”,“DE”,“DE / *”,而不是在主Servlet中提供“/ *
静态内容由默认的Servlet提供服务,空的根请求转到index.jsp,它使用默认语言调用我的主Servlet:
<jsp:include page =“/ EN /”/>(索引页上没有其他内容)
我发现使用
<mvc:default-servlet-handler />
在springMVC servlet bean定义文件适用于我。 它将任何未经注册的MVC控制器处理的请求传递给容器的原始默认处理程序,该处理程序应将其作为静态内容提供。 只要确保你没有控制器注册处理一切,它应该工作得很好。 不知道为什么@logixplayerbuild议URL重写; 你可以单独使用Spring MVC来达到他正在寻找的效果。
我build议尽可能使用filter,而不是默认的servlet。
其他两种可能性:
自己写一个FileServlet。 你会发现很多例子,它应该通过URL打开文件,并将其内容写入输出stream。 然后,使用它来提供静态文件请求。
实例化Google App Engine使用的FileServlet类,并在需要在给定的URL上提供静态文件时,调用该FileServlet上的服务(请求,响应)。
您可以将/ res / *映射到YourFileServlet,或将其从DispatcherServlets的处理中排除,或者直接从DispatcherServlet中调用它。
而且,我必须问,Spring文档对这次碰撞有什么看法? 我从来没有用过它。
我发现一个简单的解决scheme与虚拟索引文件。
创build一个映射到“/index.html”的Servlet(或者使用你想要回应的那个“/”)(这里提到的解决scheme使用通过XML的映射,我使用了带有注解@WebServlet的3.0版本)然后创build一个静态(空)文件在名为“index.html”的静态内容的根目录
我正在使用Jetty,发生了什么事是服务器识别该文件,而不是列出目录,但当问资源,我的Servlet取而代之的是控制。 所有其他静态内容不受影响。
在Embedded Jetty中,我设法通过为web.xml中的“css”目录添加映射来实现类似的function。 明确地告诉它使用DefaultServlet:
<servlet> <servlet-name>DefaultServlet</servlet-name> <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DefaultServlet</servlet-name> <url-pattern>/css/*</url-pattern> </servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <mvc:default-servlet-handler/> </beans>
如果你想使用基于注释的configuration使用下面的代码
@Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); }