Continue to original output, click on the top of the blue word to follow me


preface

Since the use of Spring Boot, there is a feeling that MVC configuration is rarely used, such as view parser, interceptor, filter, etc., which is one of the benefits of Spring Boot.

However, the default configuration provided by Spring Boot is not always suitable for actual needs, so you need to be able to customize MVC functions. This article describes how to extend and fully take over MVC.

The Spring version of the Boot

The version of Spring Boot on which this article is based is 2.3.4.release.

How do I extend MVC?

Here need to declare a premise: there is no mark @ EnableWebMvc and configuration class without any configuration class inherited WebMvcConfigurationSupport. The specific reasons will be explained in detail below.

Extending MVC is actually quite simple, just take the following steps:

  1. Create an MVC configuration class and annotate it@ConfigurationAnnotation.
  2. implementationWebMvcConfigurerThis interface and implements the required methods.

The WebMvcConfigurer interface defines custom methods for MVC related components, such as interceptors, view parsers, etc. What functions need to be customized, just need to implement.

Pre-spring Boot versions also inherit an abstract WebMvcConfigurerAdapter class, which was deprecated in 2.3.4.RELEASE as follows:

@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {}
Copy the code

For example, now that you want to add an interceptor to Spring Boot, you can override the addInterceptors() method in the MVC configuration class as follows:

/ * ** MVC extension configuration class that implements the WebMvcConfigurer interface* /
@Configuration
public class WebConfig implements WebMvcConfigurer {
  @Autowired  private RepeatSubmitInterceptor repeatSubmitInterceptor;   / * ** Rewrite the addInterceptors method to inject a custom interceptor* /  @Override  public void addInterceptors(InterceptorRegistry registry) {  registry.addInterceptor(repeatSubmitInterceptor).excludePathPatterns("/error");  } } Copy the code

In addition to interceptors, you can customize view parsing, resource mapping handlers, and other related functions, much like Spring MVC, except that Spring MVC is configured in an XML file and Spring Boot is configured in a configuration class.

How can MVC function run without configuring anything?

In the early SSM architecture, it was quite complicated to build an MVC, which needed to configure the view parser, resource mapping processor, DispatcherServlet and so on to run properly. But why Spring Boot just added a WEB module dependency to run properly? Dependencies are as follows:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency> 
Copy the code

In fact, this has involved the advanced knowledge of Spring Boot, here simply say, Spring Boot each starter will have an automatic configuration class, what is the automatic configuration class? Auto-configuration classes are classes that are automatically loaded when a Spring Boot project is started, enabling some default configurations to be configured during startup. The automatic configuration class for the WEB module is WebMvcAutoConfiguration.

WebMvcAutoConfiguration this configuration class contains the following a child WebMvcAutoConfigurationAdapter configuration class, as follows:

@Configuration(proxyBeanMethods = false)
 @Import(EnableWebMvcConfiguration.class)
 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
 @Order(0)
 public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {}
Copy the code

This piece WebMvcAutoConfigurationAdapter configuration class implements the WebMvcConfigurer this interface, this is precisely the MVC extension interface, this was made clear. Automatic configuration class is loaded, when I was in the project start so the Spring will Boot loading WebMvcAutoConfigurationAdapter when project start the MVC extension configuration class, finished ahead of some default configuration (such as built in the default view parser, resource mapping processor, etc.), That’s why nothing MVC related can be configured to run.

How to take over MVC completely? [Not recommended]

What does it mean to take over MVC? Full takeover means no Spring Boot automatic configuration is required, but all custom configurations are used.

Taking over MVC is as simple as adding an @enableWebMVC annotation to the configuration class. Add interceptors as shown in the following example:

/ * * * @EnableWebMvc: Takes over MVC, causing auto-configuration classes to fail* /
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {  @Autowired  private RepeatSubmitInterceptor repeatSubmitInterceptor;   @Override  public void addInterceptors(InterceptorRegistry registry) {  // Add interceptor  registry.addInterceptor(repeatSubmitInterceptor).excludePathPatterns("/error");  } } Copy the code

It’s nice to be able to use a single annotation to fully interface MVC, but it’s not recommended.

Why does @enableWebMVC take over MVC with a single annotation?

What??? Why is that? The auto-configuration class was mentioned earlierWebMvcAutoConfigurationSome default configurations are loaded during project startup. How do I add one@EnableWebMvcWhat about annotations?

@enablewebMVC source code is as follows:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
} Copy the code

Actually important is this @ Import (DelegatingWebMvcConfiguration. Class) annotations, Spring in the annotations, fast Import a configuration class DelegatingWebMvcConfiguration, source code is as follows:

@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {}
Copy the code

See, @ EnableWebMvc this annotation is actually import a WebMvcConfigurationSupport subtype configuration class.

And automatic configuration of the WEB module class have so a line comments @ ConditionalOnMissingBean (WebMvcConfigurationSupport. Class), the source code is as follows:

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,  ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { Copy the code

What does this annotation @conditionalonmissingbean mean? Simply put, this configuration takes effect only if there are no specified beans in the IOC container.

It’s all been revealed,@EnableWebMvcImport aWebMvcConfigurationSupportType of configuration class, resulting in automatic configuration classesWebMvcAutoConfigurationannotations@@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)Judgment forfalseSo the auto-configuration class is invalidated.

conclusion

Extending and fully taking over MVC is simple, but it is not recommended to fully take over MVC. Once it is taken over, the starter of the WEb module will be meaningless and some mVC-related configurations in the global configuration file will be invalidated.