如何处理静态内容在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,但现在情况不同了。

我有一个/static/文件夹,其中包括/styles/, /js/, /images/等,我想排除/static/*从DispatcherServlet

现在我可以让静态资源工作时,我这样做:

  <servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/</url-pattern>
</servlet-mapping>

但是我希望它有很好的url(我使用Spring MVC 3的要点),而不是登录页是www.domain.com/app/

我也不想要一个解决方案耦合到tomcat或任何其他servlet容器,因为这是(相对)低流量,我不需要一个web服务器(如apache httpd)在前面。

有干净利落的解决办法吗?

222620 次浏览

我用tuckey的urlrewritter找到了一个方法。如果你有更好的答案,请随时给出!

在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)不会被重写。

我解决这个问题的方法是将您的所有操作都放在一个特定的前缀,如“web”或“service”,并配置所有具有该前缀的url将被DispatcherServlet拦截。

如果我理解正确的话,我想我已经找到了解决你的问题的方法:

我有同样的问题,原始输出显示没有css样式,javascript或jquery文件找到。

我只是向“默认”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的名称。不太确定其他服务器是什么。

我在Spring MVC 3.0中一直在努力解决这个问题,我最初使用了UrlRewriteFilter选项。然而,我对这个解决方案并不满意,因为它“感觉不对”(我不是唯一一个这样做的人——请参阅上面春季论坛的链接,其中“hack”一词出现了几次)。

所以我想出了一个类似于上面“未知(谷歌)”的解决方案,但借鉴了所有静态内容都来自/static/(来自宠物商店应用程序的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/路径添加到CSS、JS和图像的url中。如。" $ {pageContext.request.contextPath} /静态/ 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>

在遇到并经历了这里描述的相同决策制定过程之后,我决定采用ResourceServlet建议,该建议效果非常好。

注意,你可以在这里获得更多关于如何在maven构建过程中使用webflow的信息:http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html

如果你使用标准的Maven中心存储库,工件是(与上面提到的springsource bundle相反):

<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-js</artifactId>
<version>2.0.9.RELEASE</version>
</dependency>

URLRewrite是一种“黑客”,如果你想这样称呼它的话。归结起来就是,你在重新发明轮子;因为已经有了解决方案。另一件要记住的事情是Http服务器=静态内容&应用服务器=动态内容(这就是它们的设计方式)。通过将适当的职责分配给每个服务器,您可以最大限度地提高效率……但现在,这可能只是在性能关键环境中需要考虑的问题,而像Tomcat这样的东西在大多数情况下很可能在这两个角色中都能很好地工作;但这仍然是需要记住的。

我只是在spring默认规则(/**)之前添加了三个规则到tuckey的urlrewrite.xml过滤器(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>/images/**</from>
<to>/images/$1</to>
</rule>
<rule>
<from>/**</from>
<to>/app/$1</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/$1</to>
</outbound-rule>
</urlrewrite>
这个问题在spring 3.0.4解决了。在你可以使用的地方发布 <mvc:resources mapping="..." location="..."/> spring dispatcher配置文件中的配置元素

检查Spring文档

我是这样解决的:

<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提供了(正如rozky所提到的),这是更可移植的。

在Spring 3.0中。将以下内容添加到您的servlet-config.xml(在web.xml中配置为contextConfigLocation的文件)。您还需要添加mvc名称空间,但如果您不知道如何添加,只需谷歌即可!

这对我有用

<mvc:default-servlet-handler/>

因为我在这个问题上花了很多时间,所以我想分享一下我的解决方案。自spring 3.0.4以来,有一个名为<mvc:resources/>的配置参数(更多关于参考文档网站),它可以用来提供静态资源,同时仍然使用站点根目录上的DispatchServlet。

为了使用这个,使用如下所示的目录结构:

src/
springmvc/
web/
MyController.java
WebContent/
resources/
img/
image.jpg
WEB-INF/
jsp/
index.jsp
web.xml
springmvc-servlet.xml

文件的内容应该如下所示:

src / springmvc / web / 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" />" />

我知道有一些配置可以使用静态内容,但我的解决方案是在tomcat中创建一个批量web应用程序文件夹。这个“散装web应用程序”只提供所有静态内容,而不提供应用程序。这是为实际spring webapp提供静态内容的轻松解决方案。

例如,我在tomcat上使用两个webapp文件夹。

  1. springapp:它只运行spring web应用程序,没有像imgs、js或css这样的静态内容。(专为春季应用程序。)
  2. 资源:它只提供静态内容,没有JSP, servlet,或任何类型的java web应用程序。(专用于静态内容)

如果我想使用javascript,我只需为我的javascript文件添加URI。

前女友> < em > /资源/道路/ / js / myjavascript.js < / em >

对于静态图像,我使用相同的方法。

前女友> < em > /资源/道路/ / img / myimg.jpg < / em >

最后,我把“安全约束”放在我的tomcat上,以阻止对实际目录的访问。 我将“nobody”user-roll添加到约束中,以便当人们试图访问静态内容路径时,页面生成“403禁止错误”。< / p >

到目前为止,它对我来说很有效。我还注意到许多流行的网站,如Amazon、Twitter和Facebook,它们使用不同的URI来提供静态内容。要找出这一点,只需右键单击任何静态内容并检查它们的URI。

还有另一个堆栈溢出帖子有优秀的解决方案

它似乎不是特定于Tomcat的,非常简单,而且效果非常好。我在这篇文章中用spring mvc 3.1尝试了一些解决方案,但是在获得我的动态内容服务时遇到了问题。

简单地说,它是这样添加servlet映射的:

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>

我遇到了同样的问题,发现Joris的答案非常有用。但是我还需要补充一点

<mvc:annotation-driven />

到servlet配置文件。没有该资源映射将无法工作,所有处理程序将停止工作。

我使用了两种方式,即基于spring mvc 3.0的urlrewrite和annotation。并发现基于注释的方法是最合适的,即

<annotation-driven />


<resources mapping="/resources/**" location="/resources/" />
在urlrewrite的情况下,必须定义大量的规则和一些时间也获得类未发现异常的UrlRewriteFilter,因为已经为它提供了依赖。 我发现这是由于存在传递依赖关系造成的,因此再次增加了一步,必须使用

从pom.xml中排除该依赖关系
<exclusion></exclusion> tags.

所以基于注释的方法是很好的选择。

我自己在这个问题上的经验如下。大多数与spring相关的网页和书籍似乎都建议最合适的语法如下所示。

    <mvc:resources mapping="/resources/**" location="/resources/" />

上面的语法建议您可以将静态资源(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(前端控制器)拦截所有内容,即所有动态内容。在我的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("/")

这对我来说很管用

在web . xml:

...
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</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>

...

从Spring 3开始,所有资源都需要以不同的方式映射。您需要使用标记来指定资源的位置。

例子:

<mvc:resources mapping="/resources/**" location="/resources/" />

通过这种方式,您可以指示调度程序servlet查看目录资源以查找静态内容。

这至少可以通过三种方式实现。

解决方案:

  • 将HTML作为资源文件公开
  • 指示JspServlet也处理*.html请求
  • 编写自己的servlet(或将另一个现有servlet请求传递到*.html)。

关于如何实现这一点的完整代码示例,请参考我在另一篇文章中的回答:如何映射请求到HTML文件在Spring MVC?

问题出在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>

如果您想使用基于注释的配置,请使用下面的代码

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

对于基于java的spring配置,您可以使用以下方法

使用ResourceHandlerRegistry来存储为静态资源服务的资源处理程序的注册。

更多信息@ WebMvcConfigurerAdapter,它定义了回调方法,为通过@ enablewebmvc启用的Spring MVC定制基于java的配置。

@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");


}

将css、js等静态内容放在下面的路径中

resources
->static
->css
->js
(or)
resources
->public
->css
->js