I'm trying to upgrade my spring mvc project to utilize the new annotations and get rid of my xml. Previously I was loading my static resources in my web.xml with the line:
<mvc:resources mapping="/resources/**" location="/resources/" />
Now, I'm utilizing the WebApplicationInitializer class and #EnableWebMvc annotation to startup my service without any xml files, but can't seem to figure out how to load my resources.
Is there an annotation or new configuration to pull these resources back in without having to use xml?
For Spring 3 & 4:
One way to do this is to have your configuration class extend WebMvcConfigurerAdapter, then override the following method as such:
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
Spring 5
As of Spring 5, the correct way to do this is to simply implement the WebMvcConfigurer interface.
For example:
#Configuration
#EnableWebMvc
public class MyApplication implements WebMvcConfigurer {
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
See deprecated message in: WebMvcConfigurerAdapter
Related
How to configure an Interceptor, through Annotation only(I do NOT like to register the interceptor in .XML file, I do not use .XML based configuration)?
Note : I see in example on internet it is suggesting to use org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter, when I tried to use it, I found it is DEPRECATED
I am testing on SpringWebMVC-5 with SpringBoot-2
In Spring5 you can use org.springframework.web.servlet.config.annotation.WebMvcConfigurer:
#EnableWebMvc
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(....);
}
}
I have a Spring Boot application which acts as a server for my frontend, built by webpack and included into my spring boot web archive.
I use webjars to access my frontend scripts and contents.
But there is one problem. To access webjars resources I need to use pathes like:
/webjars/jar-file-name/resource-name.ext
When in my react-js frontend code I use relateve pathes:
/resource-name.ext
I want to rebind paths of webjars to serve all resources /** from /webjars/jar-file-name
I have used this do to do it https://www.webjars.org/documentation#springmvc, but this seems to not work with Spring Boot
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/webjars/jar-file-name/");
}
}
It should work with Spring MVC, but don't work in Spring Boot.
Could you please advice the right way to do it?
I think the following code would resolve your issue:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
Here is my static content serving URL for bootstrap 3.1.0 from tutorial: http://localhost:8080/bootstrap/3.1.0/css/bootstrap.min.css
In spring the resource handler is working fine
<mvc:resources mapping="/Lab/**" location="/WEB-INF/Assets/Lab/"/>
<mvc:resources mapping="/Tools/**" location="/WEB-INF/Assets/Tools/"/>
<mvc:resources mapping="/Images/**" location="/WEB-INF/Assets/Images/"/>
How can i add multiple resources in spring boot?
The below code is not working
#Configuration
#EnableWebMvc
public class ResourceHandlers extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry
.addResourceHandler("/Lab/**")
.addResourceLocations("/WEB-INF/Assets/Lab/");
registry
.addResourceHandler("/Tools/**")
.addResourceLocations("/WEB-INF/Assets/Tools/");
registry
.addResourceHandler("/Images/**")
.addResourceLocations("/WEB-INF/Assets/Images/");
}
}
registry
.addResourceHandler("/Lab/**", "/Tools/**", "/Images/**")
.addResourceLocations("/WEB-INF/Assets/Lab/",
"/WEB-INF/Assets/Tools/",
"/WEB-INF/Assets/Images/");
It allows multiple arguments
I would like to add resource handlers using WebMvcConfigurerAdapter in Windows, but in Linux it doesn't work, so I add WebMvcConfigurationSupport.
After debug and test I find two bean will be create in both OS, but the override function of WebMvcConfigurerAdapter will be executed only at Windows and the override function of WebMvcConfigurationSupport will be executed only at Linux.
I can't find out the reason. The two configuration classes are shown below:
#Configuration
public class JxWebAppConfigurer extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("file:"+System.getProperty("user.dir")+"/src/main/webapp/");
super.addResourceHandlers(registry);
}
}
This is the other one:
#Configuration
public class JxWebConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("file:"+System.getProperty("user.dir")+"/src/main/webapp/");
super.addResourceHandlers(registry);
}
}
#EnalbeMvc is already been added at the main class
As mentioned in the #EnableWebMvc Documentation:
Adding this annotation to an #Configuration class imports the Spring
MVC configuration from WebMvcConfigurationSupport
{..}
To customize the imported configuration, implement the interface
WebMvcConfigurer or more likely extend the empty method base class
WebMvcConfigurerAdapter and override individual methods
{..}
If WebMvcConfigurer does not expose some advanced setting that needs
to be configured, consider removing the #EnableWebMvc annotation and
extending directly from WebMvcConfigurationSupport
So in effect either:
#EnableWebMvc + extending WebMvcConfigurerAdapter (suggested first option)
Extending directly from WebMvcConfigurationSupport (fallback alternative for full control)
(on both cases needed #Configuration)
The alternative solution for org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapteris org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport (I am using Spring Framework 5.0.2.RELEASE).
WebMvcConfigurerAdapter has been deprecated.
I know the reasons. As mentioned above,you should choose one select(extends WebMvcConfigurerAdapter+#EnableWebMvc or just extends WebMvcConfigurationSupport ) ;
Never use #EnableWebMvc and extending WebMvcConfigurationSupport
together!!
if use spring-boot's #EnableAutoConfiguration ,you can just extends WebMvcConfigurerAdapter and don't use #EnableMvc
Behavior differences on OS are not clear to me (classpath order?) so I'll just talk about WebMvcConfigurationSupport vs WebMvcConfigurer. Let's start with WebMvcConfigurerAdapter that implements WebMvcConfigurer, but now is deprecated because the interface has the functionality via default methods.
Now to the "support" (extending WebMvcConfigurationSupport) vs "configurer" (implementing WebMvcConfigurer). These classes have very similar methods but it works roughly like this:
Support component finds all the configurers and combines them into the final configuration.
I recently wrote quite a long post about this with code examples and I recommend experimenting with small Spring Boot applications and debug them - it's eye opening.
Boot has a default implementation of WebMvcConfigurationSupport and it does a lot of stuff - including finding beans implementing WebMvcConfigurer and using them. If you take over and implement the support class, Boot will find it, disables the default one and you're in full control. But then a lot of default auto-magic is gone and you have to use it if needed.
I have the following class:
#Configuration
#EnableWebSocketMessageBroker
#EnableScheduling
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay(
"/topic",
"/queue/");
config.setApplicationDestinationPrefixes("/app");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint(
"/wsdemo").withSockJS();
}
}
I would like to be able to NOT configure the class above whenever I'm running tests. is that possible?
Thanks!
A plain Junit test (without the spring runner) will ensure the class is not configured. you can then use mock objects (see Mockito) to satisfy any dependencies.
If you have separate "application-context.xml" for your tests, then there you must have directive:
<context:component-scan base-package="...">
...
</context:component-scan>
Modify it as below:
<context:component-scan base-package="...">
...
<context:exclude-filter type="regex" expression="{package}.WebSocketConfig"/>
</context:component-scan>