preface
In fact, I started Java Web development relatively late, which means THAT I used relatively new technologies when I was doing development, such as Spring Boot. I never used SSH. Although I used Spring MVC, it was packaged based on Spring Boot.
Of course, there are advantages and disadvantages to this, the advantages of keeping up with The Times, and the disadvantages of not having a deep understanding of what is encapsulated.
Some WEB projects inherit the WebMvcConfigurerAdapter class and then customize the configuration. There’s also this annotation in this class: @enableWebMVC.
Then two questions arise:
1. Why inherit the WebMvcConfigurerAdapter class if you want to customize the Configuration of Spring MVC
2. What is the use of @enableWebMVC annotations
With these two questions in mind, I’m ready to find out
Why inherit WebMvcConfigurerAdapter
First, Spring MVC has several core components that are configurable and extensible. These core components are not the focus of this article and will not be emphasized. You can refer to relevant materials if you need to know more about them.
I have read “Through Spring MVC Source Code Analysis and Practice” written by Han Lubiao. This book explains the nine components of Spring MVC. If you are interested, you can read it.
The question then arises, if you want to customize these configurations, why should you inherit the WebMvcConfigurerAdapter class? It is not necessary to inherit this class, but if you want to customize some advanced configuration, it is recommended to inherit it. What is advanced? Hey hey.
This class implements all the methods of the WebMvcConfigurer interface (all empty implementations). The WebMvcConfigurer interface is described in the class’s comment:
Define callback methods to customize enabling the Java-based configuration of Spring MVC with {@code @enableWebMVC}. {@code @enableWebMVC} Annotated configuration classes can implement callbacks to this interface and have the opportunity to customize the default configuration. Consider the extension {@link WebMvcConfigurerAdapter}, which provides stub implementations of all interface methods.
In my opinion, these notes have the following meanings:
-
Enable the Java Config-based configuration of Spring MVC with the @enableWebMVC annotation
-
Methods that implement the WebMvcConfigurer interface can customize the Configuration of Spring MVC
-
For the second meaning, it is recommended to inherit the WebMvcConfigurerAdapter class
-
If you want a custom Configuration subclass that inherits WebMvcConfigurerAdapter to work, it should be a Configuration class (e.g. @Configuration). After all, this class should be hosted in the Spring container so that Spring MVC will know about this subclass. Or how do these custom configurations work?)
That is, when you want to enable Spring MVC, the application uses the @enableWebMVC annotation to enable spring MVC configurations. In addition, if you want to customize these configurations, you use a configuration class that can be hosted into the Spring container. Inherit the WebMvcConfigurerAdapter class and override those methods that require custom configuration.
Here, I have a few more questions:
Q1. I inherit the WebMvcConfigurerAdapter class and rewrite the methods that need custom configuration, but how does Spring MVC know
Q2. How does Spring MVC know which configuration I want to customize, and will my customized configuration make the default configuration unavailable
Q3. How is this custom configuration subclass associated with Spring MVC
The answer to these questions should be in the @enableWebMVC annotation. So, read on
What does @enableWebMVC annotations do
What does @enableWebMVC annotations do? Take a look at the comments on the first line of the source code:
Add the annotation to the {@ code @ Configuration} class from {@ link WebMvcConfigurationSupport} import Spring MVC Configuration
That is to say, the comments should be added to the @ Configuration of annotation class (which means the class should be managed to the spring container Configuration class), and then you can from {@ link WebMvcConfigurationSupport} import spring MVC Configuration, Problems in the WebMvcConfigurationSupport classes.
@enableWebMVC annotation class
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
Copy the code
Is focused on: @ Import (DelegatingWebMvcConfiguration. Class) here, this is based on Java config format the configuration of the Import of a class, and then look at the source of the DelegatingWebMvcConfiguration:
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
Copy the code
Then understood: DelegatingWebMvcConfiguration is inherited WebMvcConfigurationSupport configuration class.
Now look at what is WebMvcConfigurationSupport first, annotation is explained:
This is the main class that provides the configuration behind the MVC Java configuration. It is typically imported by adding {@link EnableWebMvc @enableWebMVC} to the application {@Link Configuration@Configuration} class.
Another option to choose advanced is to extend directly from this class and override methods as needed, remembering to add {@Link Configuration@configuration} to subclasses and {@Link bean@bean} to override {@link bean@bean} methods. See Javadoc for {@link EnableWebMvc @enableWebMVC} for more details.
The effect of the WebMvcConfigurationSupport class, actually provided the above several spring MVC core components. If you want to extend from this class, you just need to inherit and rewrite some of its methods (see the source code for this class if you’re interested).
Now is that DelegatingWebMvcConfiguration inherited WebMvcConfigurationSupport class and wrote some of its methods, And DelegatingWebMvcConfiguration is a configuration class is managed by the spring container, focus on:
Here’s an example of the @enableWebMVC annotation:
1. Enable the capabilities provided by these core components of Spring MVC.
If you don’t understand, here’s the explanation: ‘@ EnableWebMvc annotations, need to use in a can register to the spring container configuration on the class, then @ EnableWebMvc annotations import DelegatingWebMvcConfiguration configuration class, This class inherits the spring MVC WebMvcConfigurationSupport class provides the ability of individual components and the class has been registered by the spring container.
So, where is the relationship between the @enableWebMVC annotation and the custom configuration? I think this is the second function that the @EnableWebMVC annotation provides:
2. Ability to support custom Spring MVC configurations
And it’s this ability, is the key to DelegatingWebMvcConfiguration configuration class, said the DelegatingWebMvcConfiguration class inherits from WebMvcConfigurationSupport classes and wrote some of its methods, It’s the methods it overrides that allow us to add custom configurations.
See DelegatingWebMvcConfiguration class, part of the source code for an explanation:
@Configuration public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); // Note that the beans of all spring container classes that implement the WebMvcConfigurer interface are injected as a collection of variables. // This means that we need to customize the configuration classes for spring MVC configuration, @AutoWired (Required = false) public void setConfigurers(List<WebMvcConfigurer>) @AutoWired (Required = false) public void setConfigurers(List<WebMvcConfigurer> configurers) { if (! CollectionUtils.isEmpty(configurers)) { this.configurers.addWebMvcConfigurers(configurers); } } @Override protected void configurePathMatch(PathMatchConfigurer configurer) { this.configurers.configurePathMatch(configurer); } @Override protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) { this.configurers.configureContentNegotiation(configurer); } @Override protected void configureAsyncSupport(AsyncSupportConfigurer configurer) { this.configurers.configureAsyncSupport(configurer); } @Override protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { this.configurers.configureDefaultServletHandling(configurer); } / /... }Copy the code
It doesn’t take much, just a few lines above.
This attribute is the key to DelegatingWebMvcConfiguration class:
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); / / see WebMvcConfigurerComposite class part of the source code: If... // If... this class has a property... Is a WebMvcConfigurer interface implementation class collection class WebMvcConfigurerComposite implements WebMvcConfigurer {private final List<WebMvcConfigurer> delegates = new ArrayList<WebMvcConfigurer>(); public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) { if (! CollectionUtils.isEmpty(configurers)) { this.delegates.addAll(configurers); } } @Override public void configurePathMatch(PathMatchConfigurer configurer) { for (WebMvcConfigurer delegate : this.delegates) { delegate.configurePathMatch(configurer); } } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { for (WebMvcConfigurer delegate : this.delegates) { delegate.configureContentNegotiation(configurer); }} / /... }Copy the code
Take a look at some Chinese comments in the two pieces of code I posted above. Combined with a look, so you see, DelegatingWebMvcConfiguration classes will all implements the interface WebMvcConfigurer (subclass, too, this is a Java syntax, Not to mention our own custom configuration classes that are hosted in the Spring container (because they also implement it) add these configurations.
This explains the problem of Q1 and Q3 mentioned in Section 1: My configuration class registered by the spring container, spring by means of automatic injection of all WebMvcConfigurer interface implementation class into the DelegatingWebMvcConfiguration configurers attributes, On the WebMvcConfigurerComposite class to configure all the configuration. We then call back to the implementation classes that implement the WebMvcConfigurer interface and finally add our own custom configurations.
Q2 this problem now, so, how do you know my spring MVC custom which configuration, we rewrite method in class WebMvcConfigurerComposite callback interface, if we rewrote the need custom configuration method, and naturally, the question now is the second, If you customize the configuration, will the default configuration be loaded? This depends on the configuration you customize, such as HttpMessageConverter. If you customize the configuration after overriding the configMessageConverters method, the default configuration will not be loaded. If the override method is extendMessageContertes, the custom and default methods will be loaded.
/** * Provides access to the shared {@link HttpMessageConverter}s used by the * {@link RequestMappingHandlerAdapter} and the * {@link ExceptionHandlerExceptionResolver}. * This method cannot be overridden. * Use {@link #configureMessageConverters(List)} instead. * Also see {@link #addDefaultHttpMessageConverters(List)} that can be * used to add default message converters. */ protected final List<HttpMessageConverter<? >> getMessageConverters() { if (this.messageConverters == null) { this.messageConverters = new ArrayList<HttpMessageConverter<? > > (); configureMessageConverters(this.messageConverters); If (this. MessageConverters. IsEmpty ()) {/ / here if not load the default configuration is not empty, Has explained addDefaultHttpMessageConverters annotations (enclosing messageConverters); } extendMessageConverters(this.messageConverters); } return this.messageConverters; }Copy the code
Other components, interested in the relevant information can be consulted, or turn over the source code to understand.