Static resources in Spring MVC app - spring

In my Spring mvc application I want to serve static resources using mvc:resources.
My web.xml mapping looks that:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Where main is dispatcher servlet to serve all the content
In my servlet.xml file I added:
<mvc:resources mapping="/static/**" location="/static/"/>
and it works properly when my application context is empty (like localhost:8080/), but when I deploy application in another context it doesn't work, I got 404.
I tried many combinations:
"static/**"
"*/static/**"
Nothing works.
I'm sure it's server context problem, but I have not idea (I couldn't find the solution in Google too) how to solve this. Please, help.

I was able to succesfully map my static resources using the following convention:
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

The easiest way for we that worked, was adding in the servlet-config.xml (the file that is configured in web.xml as the contextConfigLocation) the following:
<mvc:default-servlet-handler/>

Related

Integrating Spring MVC with existing application

I am trying to integrate Spring MVC with my existing application. Existing application has context root as PORTAL here is my Spring MVC setting in web.xml is
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Everything works fine and I am able to access pages through Spring MVC. Pages get data from Controller but pages doesn't load the css, img and js files.
Application Folder structure is
src
webapps
-css
-img
-js
-WEB-INF
--jsp
JSP
<link rel="stylesheet" type="text/css" href="css/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="css/poc.css"/>
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
Error
No mapping found for HTTP request
with URI [/PORTAL/css/bootstrap.css] in DispatcherServlet with name 'spring'
As Spring MVC works on URL Pattern and every request for Image and Resources came from client is separate request, So Spring is finding the matching pattern for "/bootstrap.css" to identify is there anything to serve against this Pattern.
And there is no resource mapped against this that is why you are getting this error.
You can say Spring that these are my resources and don't go for any mapping finding, if request comes with mentioned URL.
put below line in spring-servlet.xml file.
<mvc:resources mapping="/PORTAL/css/" location="/PORTAL/css/" cache-period="0" />
this will help you to get rid of css loading errors. but problem for js and image still be there,
So try to keep all resources in one resource folder and give mapping like one below,
<mvc:resources mapping="/resources/**" location="/resources/" cache-period="0" />
Also, import this xsd above in xml file,
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
hope this helps.
You are missing the ContextPath while refering the js and css files.
Prefix the resource references as mention below
<script src="${pageContext.request.contextPath}js/jquery.js"></script>
For me the problem is that you map the SpringDispatcherServlet to everything ( <url-pattern>/</url-pattern> ). You could map it to only one type of resource and then let the server serves the other types. Example :
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Then all you css, images, videos, applet jars etc will be served directly by the server while urls finishing with .htm will be served by Spring MVC.
If you need, you can also define multiple servlet mapping for the Dispatcher servlet.

Serving static content in Spring MVC (3.1.1)

My dispatcher servlet maps to the root of the app.
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I have a folder called 'static' in my webroot. It contains CSS, JS and image files. However, because of the dispatcher servlet mapping, the requests for static contents end up in 404s.
I know the solutions lying around to address this.
Make dispatcher map to a more specific URL, say :context:/app/, and then write a filter to intercept requests, and map conditionally to the default servlet, or else delegate to the spring dispatcher.
The URL rewrite trick.
using <mvc:resources />
Problem is, my mappings are XML based, and I will absolutely not scatter my mappings config all over the place in the name of using annotations. So if I use <mvc:resources />, my xml based mappings break, and all url mappings to different controllers are lost.
This is becase <mvc:resources /> overrides some settings and applies its own. But it is also the cleanest solution for static content.
Any way available to tell <mvc:resources /> to not override my xml based mappings?
<mvc:resources /> appears to be a perfect fit for your problem.
From what I understand, your DispatcherServlet is handling all requests to your server. So the resource tag should return the files at the location specified in the mvc:resources location attribute. It should not be catching anything other than what's mapped.
Are you using something along the lines of
<mvc:resources mapping="/static/**" location="/static/"/>
If it is overriding settings that aren't configurable in the tag consider instantiating your own org.springframework.web.servlet.resource.ResourceHttpRequestHandler
I do have this in the web.xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
You can provide a file extention for your controllers, e.g.
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>
Then all URLs ending in .do will go through springs DispatcherServlet.
add <mvc:default-servlet-handler/> towards the top of your web.xml file
or if you are you using annotations
#Configuration
#EnableWebMvc
public class MVCConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable("default");
}
}

How to access the images from jsp?

I am using Spring MVC 3.0.
I have to load the images which exist in the folder "images" parallel to the WEB-INFdirectory.
I have the jsp files in WEB-INF/jsp folder.
The folder structure is:
-app
--images
--WEB-INF
---jsp
---classes
...
In web.xml the url mapping for DispatcherServlet is some thing like
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Now in JSP if I load the jsp in the following way:
<img src="<%=request.getContextPath()%>/images/calogo.jpg" />
Its now working as DispatcherServlet is intercepting it I guess.
Yes you are right. Your dispatcher is intercepting your request to display the images.
According to me when you try to access the image in your jsp file it will give you 404 error.
You need to include the following line of code in your servlet.xml file.
<mvc:resources location="/images/" mapping="/images/**" />
And then everything will work.
Hope this helps you.
Cheers.
If you map / to DispatcherServlet, be sure to enable default servlet handler in Spring's config:
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" />
<!-- add this to make Spring properly handle resources (e.g., images) -->
<mvc:default-servlet-handler />
Also, do not use <%... syntax use JSTL:
<img src="<c:url value="/images/calogo.jpg" />" />
(or better - do not use JSP at all, use e.g. ThymeLeaf)

Absolute path in <mvc:resources/> instead of path relative to mapping of spring servlet

I'm trying to map a request to static resources in a spring environment. My app server is Jetty.
In web.xml, I'm mapping various url patterns to my spring servlet:
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/otherpath/*</url-pattern>
</servlet-mapping>
[many more mappings...]
Note that "/" is not mapped to my spring servlet.
In spring-servlet.xml, I'm using the mvc:resources tag to map a url to a directory with my static content:
<mvc:resources mapping="/static/**" location="/WEB-INF/static/" />
This does not work as I expected. Instead of mapping
/static/ to /WEB-INF/static/,
it maps
/static/static/ to /WEB-INF/static
The reason is that the mapping given in "mvc:resources" seems to not be relative to / but relative to the path that maps to the spring servlet.
Is there a way to consider the full path, relative to / for the mapping, not the path relative to the servlet mapping?
The solution is to not use the mvc:resources tag, but to configure the corresponding handler with a bean and a URLHandlerMapping:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
<property name="mappings">
<props>
<prop key="/static/*">staticResources</prop>
</props>
</property>
</bean>
<bean id="staticResources" class="org.springframework.web.servlet.resource.ResourceHttpRequestHandler">
<property name="locations">
<list>
<value>/WEB-INF/static/</value>
</list>
</property>
</bean>
The SimpleUrlHandlerMapping with its alwaysUseFullPath property does allow more fine-grained control over the mapping.
To answer your question with one short word. No, at least I don't think so.
The servlet looks inside it's own "space" and that is after the servlet-mapping done in web.xml. That in turn is after the mapping done i your container (like tomcat)
Would it be possible to add just one servlet to / and then add two <mvc:resource />? One with /static/** and one with /otherpath/** (or whatever you need there). If not I would go with JB Nizet's solution to add two different servlets entirely.
Or you could use <mvc:default-servlet-handler/> and <spring:url>. It worked for me.
mvc:resources doesn't seem to work when application is not started on the ROOT context.
Here's the configuration that I used (note the commented bit that was doing the resource mapping to the application started under 'localhost:8080/myapp' context, though context name shouldn't be in the spring config):
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources -->
<!--<mvc:resources location="/styles" mapping="/myapp/styles/**"/>-->
<!--<mvc:resources location="/js" mapping="/myapp/js/**"/>-->
<!-- Allows for mapping the DispatcherServlet to "/" by forwarding static resource
requests to the container's default Servlet -->
<mvc:default-servlet-handler/>
The trick is to use spring:url to resolve your application context. Here is what I used for that:
<spring:url value="/styles/site.css" var="site_style"/>
<link rel="stylesheet" href="${site_style}" type="text/css" media="screen"/>
I'm basically using relative paths to my root app folder, while spring takes care of adding the /myapp in front of it.
It's still pretty strange that mvc:resources doesn't do that on it's own, but at least this works and its still pretty neat.

Tomcat serving static resources on Spring MVC app

I'm building a Spring MVC application, and the frontController servlet is mapped in "/" intercepting all requests, I'd to be able to serve the static contents (.js,.css,.png...) from tomcat and not by Spring.
My app structure is
-webapp/
styles/
images/
WEB-INF/
views/
By default, because the frontController is mapped on the context root of my app its handles all requests but don't serve any static resource.
The mvc configurarion for static resources is follow.
<mvc:resources mapping="/resources/**" location="/"/>
And the page's code is:
<img src="resources/images/logo.png" />
I need to configure Tomcat to serve the static resources with no spring interaction.
Any suggestion?
You can remap tomcats default servlet (which handles static content), e.g.
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
Have a look at this mailing list thread and see if that does what you're looking for.
Another potential solution - Just add the following to your Spring DispatcherServlet.xml (Spring Docs)
<mvc:default-servlet-handler/>
This tag allows for mapping the DispatcherServlet to "/" (thus overriding the mapping of the container's default Servlet), while still allowing static resource requests to be handled by the container's default Servlet. It configures a DefaultServletHttpRequestHandler with a URL mapping (given a lowest precedence order) of "/**". This handler will forward all requests to the default Servlet.
Pros (as compared to #nos's solution)
The URL remapping solution behaves differently depending upon your container. Jetty/Tomcat 6 take that to mean 'map URL/images/* to WEBAPP/images/'. Tomcat < 6 (and maybe others) take that to mean 'map URL/images/ to WEBAPP/*', which is a BIG security breach.
If you want to serve a favicon.ico, robots.txt etc. from your site, then you'll have
to create additional url-mappings for them.
Cons
Spring is in the loop, which is definitely something that is unnecessary.
Additionally, irrespective of the solution that one prefers, I'd suggest adding the following to your web.xml to prevent directory listings (on, say URL/images)
<servlet>
<servlet-name>default</servlet-name>
<init-param>
<param-name>dirAllowed</param-name>
<param-value>false</param-value>
</init-param>
</servlet>

Resources