Spring <mvc:resources ... =“”>请求路由

时间:2015-08-12 00:32:05

标签: spring-mvc static-resource

TL; DR:我正在编写一个简单的Tomcat / Spring / Freemarker webapp,似乎在让Spring的DispatcherServlet遵守<mvc:resources...>配置方面遇到了很多麻烦。

请注意:AFAICT这不是其他问题的重复,因为我已尝试过其他答案中给出的解决方案。如果有人发现现有问题并且该问题提供了我错过的解决方案,我很乐意将VTC作为复制品(如果需要,可以删除此问题)。

我有一个基于Freemarker的非常简单的webapp。那部分工作正常。我有一个请求处理程序方法来处理所有请求(@RequestMapping("/**")),但希望使用/${contextPath}/static/...工具提供静态资源<mvc:resources.../>。资源位于顶级webapp目录的子目录中。

基于阅读SO上的其他问题,我添加了

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

到我的Spring配置。

无论我做什么,我希望将作为静态资源文件解析的请求发送到我的控制器的请求处理程序方法。我唯一能想到的是@RequestMapping注释优先于mvc:resources,但这并没有多大意义。

我已验证资源网址是否正确生成,即模板行

<link rel="stylesheet" href="${contextPath}/static/css/gallery.css">

产生

<link rel="stylesheet" href="/gallery/static/css/gallery.css">

并且Tomcat服务器正在接收请求,只是路由到错误的位置。

我已经阅读了关于此主题的大部分问题,我相信我做得对(例如Trying to get mvc resources to serve my static resources),但显然我错过了一些明显的东西

环境

  • Eclipse Luna
  • Java 8
  • Tomcat 8
  • Freemarker 2.3.23
  • Spring 4.2.0
  • Windows 7 SP1

已部署的布局

标准Java EE Tomcat目录结构

webapps
 |- gallery
     |- css
     |- images
     |- js
     |- META-INF
     |- WEB-INF
         |- classes
         |- lib
         |- views

Tomcat上下文定义

<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="D:\dev\tools\apache-tomcat-8.0.24\wtpwebapps\gallery" 
         path="/gallery" reloadable="true" 
         source="org.eclipse.jst.j2ee.server:gallery"/>

Spring Servlet配置

WEB-INF/main-servlet.xml

...
<mvc:resources mapping="/static/**" location="/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.mysite.gallery"/>
...

我已经尝试了这些陈述的所有可能的排序,但这似乎没有效果。我也尝试过添加

<mvc:default-servlet-handler/>

没有效果。

WEB-INF/web.xml

标准Spring MVC DispatcherServlet配置

  ...
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
      <servlet-name>main</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
      <servlet-name>main</servlet-name>
      <url-pattern>/*</url-pattern>
  </servlet-mapping>
  ...

RequestMapping方法

...
@RequestMapping("/**")
public String gallery(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp)
{
    etc...

自由标记模板

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="${contextPath}/static/css/photoswipe.css">
    <link rel="stylesheet" href="${contextPath}/static/css/default-skin/default-skin.css">
    <link rel="stylesheet" href="${contextPath}/static/css/gallery.css">
    <script src="${contextPath}/static/js/photoswipe.min.js"></script>
    <script src="${contextPath}/static/js/photoswipe-ui-default.min.js"></script>
  </head>
  <body>
    <div>
...

1 个答案:

答案 0 :(得分:2)

你在问题​​中给出了答案:我唯一能想到的是@RequestMapping注释优先于mvc:resources,但这没有多大意义。 / p>

你可能认为它没有意义,但春天的研究员应该如何决定它,至少在默认情况下......

但是你有不同的方法让静态资源在@RequestMapping带注释的控制器上具有优先权。

最简单的方法是在"order=0"标记中添加<mvc:resources.../>属性:

<mvc:resources mapping="/static/**" location="/" order="0"/>

并在<mvc:annotation-driven/>

之前将其写入WEB-INF / main-servlet.xml

我使用Spring 3.2.4进行测试,它的工作方式与您想要的一样。但它看起来像驱动弹簧框架,它不是为其设计的,所以我不能保证它将适用于其他版本。

您还可以将调度程序servlet映射到/而不是/*。这样,servlet容器可以直接提供的所有静态资源(以及JSP)都将是。该映射的主要警告是,Spring调度程序servlet将不再提供root。一种可能的解决方法是使用/home URL作为根控制器,并将欢迎文件放在web xml中:

<servlet>
  <servlet-name>main</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

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

<welcome-file-list>
    <welcome-file>/home</welcome-file>
</welcome-file-list>

这样,您甚至不需要使用/mappings/images/img.gif,只需使用/images/img.gif /。

但还有另一个警告,我一直接受(因为我找不到任何解决方法):如果/url由一个控制器提供,/url.jsp/url.jpeg会给出一个404错误。由于容器默认servlet知道.jpeg.jsp个文件,它将捕获请求并失败。