I am developing a webapp using Spring MVC 3 and have the DispatcherServlet
catching all requests to \'/\' like so (web.xml):
Since I spent a lot of time on this issue, I thought I'd share my solution. Since spring 3.0.4, there is a configuration parameter that is called <mvc:resources/>
(more about that on the reference documentation website) which can be used to serve static resources while still using the DispatchServlet on your site's root.
In order to use this, use a directory structure that looks like the following:
src/
springmvc/
web/
MyController.java
WebContent/
resources/
img/
image.jpg
WEB-INF/
jsp/
index.jsp
web.xml
springmvc-servlet.xml
The contents of the files should look like:
src/springmvc/web/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" />" />
Hope this helps :-)
I used both ways that is urlrewrite and annotation based in spring mvc 3.0.x and found that annotation based approach is most suitable that is
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
In case of urlrewrite,have to define lots of rule and some time also get class not found exception for UrlRewriteFilter as already provided the dependency for it. I found that it's happening due to the presence of transitive dependency, so again one step will increased and have to exclude that dependency from pom.xml using
<exclusion></exclusion> tags.
So annotation based approach will be the good deal.
This can be achieved in at least three ways.
Solutions:
For complete code examples how to achieve this please reffer to my answer in another post: How to map requests to HTML file in Spring MVC?
Place static contents like css ,js in following path
resources
->static
->css
->js
(or)
resources
->public
->css
->js
This did the real job in my case
in 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>
...
My own experience with this problem is as follows. Most Spring-related web pages and books seem to suggest that the most appropriate syntax is the following.
<mvc:resources mapping="/resources/**" location="/resources/" />
The above syntax suggests that you can place your static resources (CSS, JavaScript, images) in a folder named "resources" in the root of your application, i.e. /webapp/resources/.
However, in my experience (I am using Eclipse and the Tomcat plugin), the only approach that works is if you place your resources folder inside WEB_INF (or META-INF). So, the syntax I recommend is the following.
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
In your JSP (or similar) , reference the resource as follows.
<script type="text/javascript"
src="resources/my-javascript.js">
</script>
Needless to mention, the entire question only arose because I wanted my Spring dispatcher servlet (front controller) to intercept everything, everything dynamic, that is. So I have the following in my 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>
Finally, since I'm using current best practices, I have the following in my front controller servlet xml (see above).
<mvc:annotation-driven/>
And I have the following in my actual controller implementation, to ensure that I have a default method to handle all incoming requests.
@RequestMapping("/")
I hope this helps.