首页 文章

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

提问于
浏览
191

我正在使用Spring MVC 3开发一个webapp,并且 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之前,我会 grab 所有* .html并将其发送到 DispatcherServlet ,但现在它是一个不同的球赛 .

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

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

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

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

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

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

22 回答

  • 15

    由于我花了很多时间在这个问题上,我以为我会分享我的解决方案 . 从Spring 3.0.4开始,有一个名为 <mvc:resources/> 的配置参数(更多关于reference documentation website的配置参数),它可以用来提供静态资源,同时仍然使用站点根目录下的DispatchServlet .

    要使用它,请使用如下所示的目录结构:

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

    文件的内容应如下所示:

    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";
     }
    }
    

    的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" />" />
    

    希望这可以帮助 :-)

  • 0

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

    检查Spring Documentation

  • 1

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

    这对我行得通

    <mvc:default-servlet-handler/>
    

    问候

    Ayub Malik

  • 2

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

    我有同样的问题,原始输出显示没有找到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>
    

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

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

  • 1

    还有另一个堆栈溢出帖子有excellent solution .

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

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

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

    我刚刚在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>
    

    我对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>
    
  • 6

    我找到了一种方法,使用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>
    

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

  • 0

    我对这个问题的经验如下 . 大多数与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("/")
    

    我希望这有帮助 .

  • 18

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

    <mvc:annotation-driven />
    

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

  • 12

    如果你想调用它,那么URLRewrite就像是一个“hack” . 它归结为,你正在重新发明轮子;因为已有解决方案 . 另一件需要记住的事情是Http Server =静态内容和App服务器=动态内容(这就是它们的设计方式) . 通过将适当的职责委派给每个服务器,您可以最大限度地提高效率......但是现在这一天可能只是性能关键环境中的一个问题,而Tomcat在大多数情况下最有可能在这两个角色中都能很好地工作;但是仍然要记住这一点 .

  • 0

    我这样解决了:

    <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 provides(如rozky所提到的),它更加便携 .

  • 2

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

    示例:

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

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

  • 258

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

  • 47

    我只是在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>/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>
    
  • 1

    我知道有一些配置可以使用静态内容,但我的解决方案是我只是在你的tomcat中创建一个批量的web应用程序文件夹 . 这个“批量网络应用程序”仅在不提供应用程序的情况下提供所有静态内容 . 这是为您的实际 spring webapp提供静态内容的无痛且简单的解决方案 .

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

    • springapp :它只运行没有像imgs,js或css这样的静态内容的spring web应用程序 . (专用于 Spring 季应用程序 . )

    • resources :它只提供没有JSP,servlet或任何类型的Java Web应用程序的静态内容 . (专用于静态内容)

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

    EX> /resources/path/to/js/myjavascript.js

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

    EX> /resources/path/to/img/myimg.jpg

    最后,当人们试图访问静态内容路径时,我把“ security-constraint " on my tomcat to block the access to actual directory. I put " nobody " user-roll to the constraint so that the page generates " 403禁止错误” .

    到目前为止,它对我来说非常好 . 我还注意到许多流行的网站,如亚马逊,Twitter和Facebook,他们使用不同的URI来提供静态内容 . 要找到这一点,只需右键单击任何静态内容并检查其URI .

  • 0

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

    <annotation-driven />
    
    <resources mapping="/resources/**" location="/resources/" />
    

    在urlrewrite的情况下,必须定义大量规则,并且还有一些时间也为UrlRewriteFilter获取类找不到异常,因为已经为它提供了依赖性 . 我发现由于存在传递依赖性而发生这种情况,所以再一步会增加并且必须从pom.xml中排除该依赖关系

    <exclusion></exclusion> tags.
    

    因此基于注释的方法将是一个很好的协议 .

  • 38

    在我的案例中,这确实起了作用

    在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>
    

    ...

  • 1

    在遇到并经历同样的决定之后在这里描述的制作过程中,我决定使用ResourceServlet提案,该提议非常好用 .

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

    如果您使用标准Maven中央存储库,则工件(与上面提到的泉源包相反):

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

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

    Solutions

    • 将html暴露为资源文件

    • 指示JspServlet也处理* .html请求

    • 编写自己的servlet(或传递给另一个现有的servlet请求* .html) .

    有关完整的代码示例如何实现这一点,请在另一篇文章中回答我的回答:How to map requests to HTML file in Spring MVC?

  • 8

    问题在于URLPattern

    将servlet映射上的URL模式从“/”更改为“/ *”

  • 2
    <?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();
        }
    
  • 11

    对于基于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");
    
        }
    

相关问题