I\'ve mapped the Spring MVC dispatcher as a global front controller servlet on /*
.
The reason for the collision seems to be because, by default, the context root, "/", is to be handled by org.apache.catalina.servlets.DefaultServlet. This servlet is intended to handle requests for static resources.
If you decide to bump it out of the way with your own servlet, with the intent of handling dynamic requests, that top-level servlet must also carry out any tasks accomplished by catalina's original "DefaultServlet" handler.
If you read through the tomcat docs, they make mention that True Apache (httpd) is better than Apache Tomcat for handling static content, since it is purpose built to do just that. My guess is because Tomcat by default uses org.apache.catalina.servlets.DefaultServlet to handle static requests. Since it's all wrapped up in a JVM, and Tomcat is intended to as a Servlet/JSP container, they probably didn't write that class as a super-optimized static content handler. It's there. It gets the job done. Good enough.
But that's the thing that handles static content and it lives at "/". So if you put anything else there, and that thing doesn't handle static requests, WHOOPS, there goes your static resources.
I've been searching high and low for the same answer and the answer I'm getting everywhere is "if you don't want it to do that, don't do that".
So long story short, your configuration is displacing the default static resource handler with something that isn't a static resource handler at all. You'll need to try a different configuration to get the results you're looking for (as will I).
I've run into this also and never found a great solution. I ended up mapping my servlet one level higher in the URL hierarchy:
<servlet-mapping>
<servlet-name>home</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
And now everything at the base context (and in your /res directory) can be served up by your container.
<?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>
and if you want to use annotation based configuration use below code
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
In section "12.2 Specification of Mappings" of the Servlet Specification, it says:
A string containing only the ’/’ character indicates the "default" servlet of the application.
So in theory, you could make your Servlet mapped to /*
do:
getServletContext().getNamedDispatcher("/").forward(req,res);
... if you didn't want to handle it yourself.
However, in practice, it doesn't work.
In both Tomcat and Jetty, the call to getServletContext().getNamedDispatcher('/')
returns null
if there is a servlet mapped to '/*'
If you use Tomcat, you can map resources to the default servlet:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
and access your resources with url http://{context path}/static/res/...
Also works with Jetty, not sure about other servlet containers.
'Static' files in App Engine aren't directly accessible by your app. You either need to upload them twice, or serve the static files yourself, rather than using a static handler.