How to use spring MVC <mvc: resources> tag in context of java application?
I created the โcurrentlyโ simple and basic spring web application. I use the deployment descriptor as a simple web.xml file and then the application context as an XML file.
Although, now I wanted to try to create my entire spring web application using only java files. So I created my WebApplicationInitializer instead of the usual deployment descriptor and my application context that uses the @Configuration annotation.
Deployment descriptor
package dk.chakula.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration.Dynamic; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; /** * * @author martin * @since 12-1-2012 * @version 1.0 */ public class Initializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { registerDispatcherServlet(servletContext); } private void registerDispatcherServlet(final ServletContext servletContext) { WebApplicationContext dispatcherContext = createContext(ChakulaWebConfigurationContext.class); DispatcherServlet dispatcherServlet = new DispatcherServlet(dispatcherContext); Dynamic dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } private WebApplicationContext createContext(final Class<?>... annotatedClasses) { AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); context.register(annotatedClasses); return context; } } //End of class Initializer Application context
package dk.chakula.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.view.UrlBasedViewResolver; import org.springframework.web.servlet.view.tiles2.TilesConfigurer; import org.springframework.web.servlet.view.tiles2.TilesView; /** * * @author martin * @since 12-01-2013 * @version 1.0 */ @Configuration @EnableWebMvc @ComponentScan("dk.chakula.web") public class ChakulaWebConfigurationContext { @Bean public TilesConfigurer setupTilesConfigurer() { TilesConfigurer configurer = new TilesConfigurer(); String[] definitions = {"/layout/layout.xml"}; configurer.setDefinitions(definitions); return configurer; } @Bean public UrlBasedViewResolver setupTilesViewResolver() { UrlBasedViewResolver viewResolver = new UrlBasedViewResolver(); viewResolver.setViewClass(TilesView.class); return viewResolver; } } //End of class ChakulaWebConfigurationContext My problem is that I cannot find a way to "isolate" my mapping to a resource folder that contains images, css javascript, etc. When my application context is in java.
In the usual context of an XML application, I used this tag to isolate the mapping in / resources /
<mvc:resources mapping="/resources/**" location="/resources/" /> How can I do this, so my web application can use my images, css, etc.
To be able to serve static resources in a Spring MVC application, you need two XML tags: <mvc:resources/> and <mvc:default-servlet-handler/> . The same thing in a Java Spring based configuration would be:
@Configuration @EnableWebMvc public class WebMvcConfig extends WebMvcConfigurerAdapter { // equivalents for <mvc:resources/> tags @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926); registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926); registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926); } // equivalent for <mvc:default-servlet-handler/> tag @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } // ... other stuff ... } Note that since the @EnableWebMvc annotation is @EnableWebMvc , there is no need to extend WebMvcConfigurationSupport directly, and you just need to extend WebMvcConfigurerAdapter . See the JavaDoc for @EnableWebMvc for more details .
After using the hours on the Internet reading about Spring MVC 3 using only java files, I fell on some articles that took the approach, extending it from the WebMvcConfigurationSupport class, and then overriding 2 methods - addResourceHandler (ResourceHandlerRegistry) and ResourceHandlerMapping ().
Now my new application context is as follows.
package dk.chakula.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.view.UrlBasedViewResolver; import org.springframework.web.servlet.view.tiles2.TilesConfigurer; import org.springframework.web.servlet.view.tiles2.TilesView; /** * * @author martin * @since 12-01-2013 * @version 1.0 */ @Configuration @EnableWebMvc @ComponentScan("dk.chakula.web") public class ChakulaWebConfigurationContext extends WebMvcConfigurationSupport { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); } @Override @Bean public HandlerMapping resourceHandlerMapping() { AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) super.resourceHandlerMapping(); handlerMapping.setOrder(-1); return handlerMapping; } @Bean public TilesConfigurer setupTilesConfigurer() { TilesConfigurer configurer = new TilesConfigurer(); String[] definitions = {"/layout/layout.xml"}; configurer.setDefinitions(definitions); return configurer; } @Bean public UrlBasedViewResolver setupTilesViewResolver() { UrlBasedViewResolver viewResolver = new UrlBasedViewResolver(); viewResolver.setViewClass(TilesView.class); return viewResolver; } } //End of class ChakulaWebConfigurationContext As I understand it, we had to override addResourceHandler to add the location and resource mapping to the registry. After that, we needed a bean that returned a HandlerMapping object. The order of this HandlerMapping should be set to -1, because since I could read from the Spring documentation, then -1 means
HandlerMapping is ordered by Integer.MAX_VALUE-1 to serve static resource requests.
My application can now upload css files and images to its views, and I would like to tell you others how to answer this question, so people could use this in the future.
Try the following:
@Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); }