如何在Spring MVC中处理静态内容?

ham*_*amo 197 spring-mvc

我正在使用Spring MVC 3开发一个webapp,并且DispatcherServlet像'so'一样捕获所有请求(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>
Run Code Online (Sandbox Code Playgroud)

现在这可以像宣传的那样工作,但是我如何处理静态内容呢?以前,在使用RESTful URL之前,我会抓住所有*.html并将其发送给DispatcherServlet,但现在它是一个不同的球类游戏.

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

现在,当我这样做时,我可以获得静态资源:

  <servlet-mapping>
    <servlet-name>app</servlet-name>
    <url-pattern>/app/</url-pattern>
  </servlet-mapping>
Run Code Online (Sandbox Code Playgroud)

但我希望它有很好的URL(我使用Spring MVC 3)而不是登陆页面www.domain.com/app/

我也不希望解决方案耦合到tomcat或任何其他servlet容器,并且因为这是(相对)低流量我不需要网络服务器(如apache httpd)infront.

有一个干净的解决方案吗?

Jor*_*ris 262

由于我花了很多时间在这个问题上,我以为我会分享我的解决方案.从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
Run Code Online (Sandbox Code Playgroud)

文件的内容应如下所示:

SRC /用SpringMVC /网络/ 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";
 }
}
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

的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>
Run Code Online (Sandbox Code Playgroud)

的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" />" />
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助 :-)

  • 这个例子应该在Spring用户指南中 - 这是我在这个主题上看到的最好的.谢谢Joris! (11认同)
  • 您还可以使用<mvc:resources mapping ="/**"location ="/ resources /"/>,它将映射到根目录.(即:根将包含资源和jsps).这可以节省你在任何地方使用c:url (4认同)
  • 正如@Bane所指出的,<c:url value = ... />是此解决方案的关键部分.你(或任何人)会介意告诉我为什么吗?谢谢! (2认同)

roz*_*zky 46

在Spring 3.0.4.RELEASE中可以解决此问题,您可以在spring repatcher <mvc:resources mapping="..." location="..."/> 配置文件中使用 配置元素.

检查Spring文档

  • 虽然实际上并没有"错误",但这个答案太简短了,因为Spring自己的文档(你引用作为你的答案)似乎缺少某些东西.检查Joris的答案是否有更完整的答案......不是因为它很冗长,而是事实上他提到使用<c:url ...>,你的答案和Spring的dox都没有提到 - 并证明了是解决方案的关键部分. (5认同)

Ayu*_*lik 38

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

这对我行得通

<mvc:default-servlet-handler/>
Run Code Online (Sandbox Code Playgroud)

问候

Ayub Malik


小智 20

如果我正确理解您的问题,我想我找到了解决您问题的方法:

我有同样的问题,原始输出显示没有找到CSS样式,javascripts或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>
Run Code Online (Sandbox Code Playgroud)

这应该过滤掉DispatcherRequest对象的javascript和css文件请求.

再次,不确定这是否是你所追求的,但它对我有用.我认为"default"是JBoss中默认servlet的名称.不太确定它对于其他服务器是什么.

  • 你可以在同一个`<servlet-mapping>`中添加所有`<url-pattern>`标签 (3认同)

小智 16

还有另一个堆栈溢出帖子,它有一个很好的解决方案.

它似乎不是特定于Tomcat,很简单,而且效果很好.我已经尝试了这篇文章中的几个解决方案与spring mvc 3.1但是在获取我的动态内容时遇到了问题.

简而言之,它说添加这样的servlet映射:

<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
Run Code Online (Sandbox Code Playgroud)


ham*_*amo 11

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

在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>
Run Code Online (Sandbox Code Playgroud)

在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>    
Run Code Online (Sandbox Code Playgroud)

这意味着任何带有'.'的uri.在其中(例如style.css)将不会被重写.

  • 更好的答案是Spring 3的`<mvc:resources />`,正如@Joris所证明的那样. (5认同)

nic*_*dos 11

我刚刚在Spring MVC 3.0中解决了这个问题,我最初选择了UrlRewriteFilter选项.但是我对这个解决方案并不满意,因为它"感觉不对"(我不是唯一的一个 - 请参阅上面的链接,弹出论坛中出现"hack"这个词几次).

所以我想出了一个类似上面的"未知(谷歌)"的解决方案,但借用了从/ static /(取自Pet Store应用程序的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>
Run Code Online (Sandbox Code Playgroud)

我对JSP所做的唯一更改是为CSS,JS和图像添加/ static/path到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>
Run Code Online (Sandbox Code Playgroud)

  • 回顾Spring Pet Clinic应用程序的标准(非Roo)版本,我注意到"default"的servlet定义已注释掉了附加注释:"在容器(GlassFish)中取消注释,但未声明此隐含的定义开箱即用".默认的显式包声明是org.apache.catalina.servlets.DefaultServlet.所以这可能是你的"开箱即用"资源servlet(?).我使用Jetty开发工作,似乎Jetty没有提供隐式默认servlet(如Glassfish). (2认同)

Pun*_*mba 8

我对这个问题的经验如下.大多数与Spring相关的网页和书籍似乎都表明最合适的语法如下.

    <mvc:resources mapping="/resources/**" location="/resources/" />
Run Code Online (Sandbox Code Playgroud)

上面的语法建议您可以将静态资源(CSS,JavaScript,图像)放在应用程序根目录中名为"resources"的文件夹中,即/ webapp/resources /.

但是,根据我的经验(我使用Eclipse和Tomcat插件),唯一有效的方法是将资源文件夹放在 WEB_INF(或META-INF)中.所以,我推荐的语法如下.

    <mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
Run Code Online (Sandbox Code Playgroud)

在JSP(或类似)中,引用资源如下.

<script type="text/javascript"
        src="resources/my-javascript.js">
</script>
Run Code Online (Sandbox Code Playgroud)

不用说,整个问题只是因为我希望我的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>
Run Code Online (Sandbox Code Playgroud)

最后,因为我正在使用当前的最佳实践,所以我在前端控制器servlet xml中有以下内容(参见上文).

<mvc:annotation-driven/>
Run Code Online (Sandbox Code Playgroud)

我在实际的控制器实现中有以下内容,以确保我有一个默认方法来处理所有传入的请求.

@RequestMapping("/")
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.


Sus*_*ath 6

我遇到了同样的问题,发现Joris的回答很有帮助.但另外我需要补充一下

<mvc:annotation-driven /> 
Run Code Online (Sandbox Code Playgroud)

到servlet配置文件.如果没有该资源映射将无法工作,所有处理程序将停止工作.希望这会对某人有所帮助.


归档时间:

查看次数:

210796 次

最近记录:

6 年,5 月 前