TL;DR: I'm writing a simple Tomcat/Spring/Freemarker webapp and seem to be having a lot of trouble getting Spring's DispatcherServlet to honor <mvc:resources...>
configuration.
PLEASE NOTE: AFAICT this is not a duplicate of other questions since I've tried the solutions given in other answers. If someone finds an existing question and that question provides a solution I missed, I'll gladly VTC as a dup (or delete this question if desired).
I have a very simple webapp based on Freemarker. That part is working fine. I have a single request-handler method to handle all requests (@RequestMapping("/**")
) but wish to serve static resources /${contextPath}/static/...
using the <mvc:resources.../>
facility. The resources are located in subdirectories of the top-level webapp directory.
Based on reading other questions on SO I added
<mvc:resources mapping="/static/**" location="/" />
to my Spring configuration.
No matter what I do, requests that I expect to be resolved as a static resource file are being sent to the request handler method of my controller instead. The only thing I can think of is that the @RequestMapping
annotation has precedence over mvc:resources
, but that doesn't make a lot of sense.
I have verified that the resource URLs are being generated correctly, i.e. the template line
<link rel="stylesheet" href="${contextPath}/static/css/gallery.css">
generates
<link rel="stylesheet" href="/gallery/static/css/gallery.css">
and the request is being received by the Tomcat server, just routed to the wrong place.
I've read most of the questions on SO about this subject and I believe I'm doing it right (see for example Trying to get mvc resources to serve my static resources), but clearly I'm missing something obvious.
Environment
- Eclipse Luna
- Java 8
- Tomcat 8
- Freemarker 2.3.23
- Spring 4.2.0
- Windows 7 SP1
Deployed Layout
Standard Java EE Tomcat directory structure
webapps
|- gallery
|- css
|- images
|- js
|- META-INF
|- WEB-INF
|- classes
|- lib
|- views
Tomcat Context Definition
<?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 Config
WEB-INF/main-servlet.xml
...
<mvc:resources mapping="/static/**" location="/" />
<mvc:annotation-driven/>
<context:component-scan base-package="com.mysite.gallery"/>
...
I've tried all possible orderings of these statements but that seems to have no effect. I also tried adding
<mvc:default-servlet-handler/>
with no effect.
WEB-INF/web.xml
Standard Spring MVC DispatcherServlet config
...
<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 method
...
@RequestMapping("/**")
public String gallery(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp)
{
etc...
Freemarker Template
<!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>
...