SpringBoot study notes 6-MVC configuration principle

https://www.cnblogs.com/cxuanBlog/p/11179439.htmlOfficial
website reading
Before writing the project, we still need to know one thing, that is, what configuration has SpringBoot made to our SpringMVC, including how to extend and how to customize .

Only when these are clear, we will be more comfortable using it in the future. Path 1: Source code analysis, Path 2: Official documents
Insert picture description here

Let's compare it carefully and see how it is implemented. It tells us that SpringBoot has automatically configured SpringMVC for us, and then what things have been automatically configured?

ContentNegotiatingViewResolver content negotiation view resolver

ViewResolver is automatically configured, which is the view resolver of SpringMVC that we learned before;

That is, the view object (View) is obtained according to the return value of the method, and then the view object determines how to render (forward, redirect).

Let's take a look at the source code here: we find WebMvcAutoConfiguration, and then search for ContentNegotiatingViewResolver. Find the following method!

Insert picture description here
We can click into this category to see! Find the corresponding parsing view code;
Insert picture description here
we continue to click in to see, how did he get the candidate view?

I saw in getCandidateViews that he took all the view resolvers, performed a while loop, and resolved them one by one!

Insert picture description here

So I came to the conclusion: ContentNegotiatingViewResolver this view resolver is used to combine all view resolvers

Let's study his combinatorial logic again, and see that there is an attribute viewResolvers, and see where it is assigned!
Insert picture description here
Since it is looking for a view resolver in the container, can we guess that we can implement a view resolver?

We can add a view resolver to the container ourselves; this class will help us automatically assemble it; let's implement it

Custom view resolver

1. Let's try to write a view parser in our main program;
learn more about
@Configuration annotation
package com.zhou.config;
@bean annotation



import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Locale;
//如果 ,你想 diy 一些定制化的功能,只要实现这个组件,然后将它交给springboot,springboot就会帮我们自动装配!
//扩展spring mvc ,dispatchServlet
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    
    



    //在一个方法上使用@Bean注解就表明这个方法需要交给Spring进行管理。
     @Bean
    public ViewResolver myViewResolver(){
    
    
        return new MyViewResolver();
    }


    //public interface ViewResolver 实现了视图解析器接口的类,我们就可以把他看作视图解析器
    //自定义一个自己的视图解析器MyViewResolver
    public static  class MyViewResolver implements ViewResolver{
    
    


        @Override
        public View resolveViewName(String s, Locale locale) throws Exception {
    
    
            return null;
        }
    }


}

Insert picture description here
2. How do we see if the view parser we wrote is working?

Let's add a breakpoint to the doDispatch method in DispatcherServlet for debugging, because all requests will go to this method
Insert picture description here

3. We start our project, and then visit a page at random to look at the Debug information;

I found this,
Insert picture description here
so if we want to use our own customized things, we only need to add this component to the container! SpringBoot will do the rest for us!

Formatter and converter

Find the format converter:

@Bean
@Override
public FormattingConversionService mvcConversionService() {
    
    
    // 拿到配置文件中的格式化规则
    WebConversionService conversionService = 
        new WebConversionService(this.mvcProperties.getDateFormat());
    addFormatters(conversionService);
    return conversionService;
}

Click to go:

public String getDateFormat() {
    
    
    return this.dateFormat;
}

/**
* Date format to use. For instance, `dd/MM/yyyy`. 默认的
 */
 private String dateFormat;

As you can see in our Properties file, we can configure it automatically!

If you configure your own formatting method, it will be registered in the Bean to take effect. We can configure the date formatting rules in the configuration file: the
Insert picture description here
Insert picture description here
rest will not be examples one by one, you can go on and study more!
Modifying the default configuration of SpringBoot
so many automatic configurations, the principle is the same, through the analysis of the principle of automatic configuration of WebMVC, we have to learn a way of learning, through the source code exploration, and draw conclusions; this conclusion must belong to our own, And a pass Belden.

The bottom layer of SpringBoot uses a lot of these design details, so it's okay to read the source code more! get conclusion;

When SpringBoot automatically configures many components, first see if there is any user-configured in the container (if the user configures @bean), if there is, use the user-configured, if not, use the auto-configured;

If there can be multiple components, such as our view resolver, combine the user configuration with the default one!

The official SpringMVC documentation for extensions is as follows:


If you want to keep Spring Boot MVC features and you want to add additional MVC configuration 
(interceptors, formatters, view controllers, and other features), you can add your own @Configuration 
class of type WebMvcConfigurer but without @EnableWebMvc. If you wish to provide custom instances
 of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or 
 ExceptionHandlerExceptionResolver, you can declare a WebMvcRegistrationsAdapter instance to 
 provide such components.

What we have to do is to write a @Configuration annotation class, and the type must be WebMvcConfigurer, and the @EnableWebMvc annotation cannot be marked yet; let's write one ourselves; we create a new package called config, and write a class MyMvcConfig;

//应为类型要求为WebMvcConfigurer,所以我们实现其接口
//可以使用自定义类扩展MVC的功能
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    
    

     @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    
    
        registry.addViewController("/").setViewName("login");
        registry.addViewController("/index.html").setViewName("login");
        registry.addViewController("/main.html").setViewName("index");
    }
}

Let's go to the browser to visit:
Insert picture description here
it did jump over! So, we want to extend SpringMVC, and the official recommends us to use it this way, not only to ensure that SpringBoot retains all the automatic configuration, but also to use our extended configuration!

We can analyze the principle:

1. WebMvcAutoConfiguration is the automatic configuration class of SpringMVC, which has a class WebMvcAutoConfigurationAdapter

2. There is an annotation on this class, which will be imported when doing other automatic configuration: @Import(EnableWebMvcConfiguration.class)

3. Let's click into the EnableWebMvcConfiguration class to take a look. It inherits a parent class: DelegatingWebMvcConfiguration

There is such a piece of code in this parent class:

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    
    
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
    
  // 从容器中获取所有的webmvcConfigurer
    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
    
    
        if (!CollectionUtils.isEmpty(configurers)) {
    
    
            this.configurers.addWebMvcConfigurers(configurers);
        }
    }
}

4. We can look for a viewController we just set up as a reference in this class, and find that it calls a


protected void addViewControllers(ViewControllerRegistry registry) {
    
    
    this.configurers.addViewControllers(registry);
}

5. Let's click in and take a look


public void addViewControllers(ViewControllerRegistry registry) {
    
    
    Iterator var2 = this.delegates.iterator();

    while(var2.hasNext()) {
    
    
        // 将所有的WebMvcConfigurer相关配置来一起调用!包括我们自己配置的和Spring给我们配置的
        WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
        delegate.addViewControllers(registry);
    }

}

So I came to the conclusion: all WebMvcConfiguration will be used, not only Spring's own configuration class, but our own configuration class will of course be called;

Fully take over SpringMVC

Official documents:

If you want to take complete control of Spring MVC
you can add your own @Configuration annotated with @EnableWebMvc.

Fully takeover means: SpringBoot does not need to automatically configure SpringMVC, all is configured by ourselves!

Just add a @EnableWebMvc to our configuration class.

Let's see if we take over SpringMVC in an all-round way, the static resource mapping that we configured for us by SpringBoot will definitely be invalid, we can test it;

Before adding comments, visit the homepage

We found that all SpringMVC auto-configuration has failed! Back to the original state;

Of course, in our development, it is not recommended to use the full takeover of SpringMVC

Thinking about the problem? Why did I add a comment and the automatic configuration is invalid! Let's look at the source code:

1. It is found here that it imported a class, we can continue to see
Insert picture description here
Insert picture description here

2. It inherits a parent class WebMvcConfigurationSupport
Insert picture description here
3. Let's review the Webmvc automatic configuration class.
Insert picture description here
To summarize: @EnableWebMvc imported the WebMvcConfigurationSupport component;

The imported WebMvcConfigurationSupport is just the most basic function of SpringMVC!

There will be a lot of extended configuration in SpringBoot, as long as we see this, we should pay more attention~

Guess you like

Origin blog.csdn.net/qq_44788518/article/details/114868564