04-Simple functional analysis of web development

img

1 SpringMVC auto-configuration overview

Spring Boot provides auto-configuration for Spring MVC that works well with most applications. (We don't need custom configuration in most scenarios)

The auto-configuration adds the following features on top of Spring’s defaults:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • Content Negotiation View Resolver and BeanName View Resolver
  • Support for serving static resources, including support for WebJars (covered later in this document)).

    • Static resources (including webjars)
  • Automatic registration of Converter, GenericConverter, and Formatter beans.

    • automatic registrationConverter,GenericConverter,Formatter
  • Support for HttpMessageConverters (covered later in this document).

    • Support HttpMessageConverters(later we cooperate with content negotiation to understand the principle)
  • Automatic registration of MessageCodesResolver (covered later in this document).

    • Automatic registration MessageCodesResolver(for internationalization)
  • Static index.html support.

    • Static index.html page support
  • Custom Favicon support (covered later in this document).

    • customizeFavicon
  • Automatic use of a ConfigurableWebBindingInitializer bean (covered later in this document).

    • Automatic use ConfigurableWebBindingInitializer, (DataBinder is responsible for binding request data to JavaBeans)

If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcConfigurer but without @EnableWebMvc.

Do not use the @EnableWebMvc annotation. use @Configuration + WebMvcConfigurer custom rules

If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep the Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instances of those components.

Declares WebMvcRegistrations to change the default underlying component

If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc, or alternatively add your own @Configuration-annotated DelegatingWebMvcConfiguration as described in the Javadoc of @EnableWebMvc.

use @EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC

2 Simple functional analysis

2.1 Static resource access

2.1.1 Static resource directory

As long as the static resources are on the classpath: called /static(or /publicor /resourcesor/META-INF/resources

  • Access: current project root path / + static resource name

  • Principle: 静态映射/**.

    When a request comes in, first go to the Controller to see if it can be processed. All requests that cannot be processed are handed over to the static resource handler. If the static resource is not found, it will respond with a 404 page.

  • Change the default static resource path

    spring:
      web:
        resources:
          static-locations: classpath:/abc
    

2.1.2 Static resource access prefix

(default no prefix)

spring:
  mvc:
    static-path-pattern: /res/**

Current project + static-path-pattern+ static resource name = find in the static resource folder

2.1.3 webjar

automap / webjars /**

webjars official website

		<dependency>
            <groupId>org.webjars.npm</groupId>
            <artifactId>jquery</artifactId>
            <version>3.6.0</version>
        </dependency>

Access address: http://localhost:8080/webjars/jquery/3.6.0/dist/jquery.js The address behind should follow the package path in the dependency

2.2 Welcome page support

  • index.html under the static resource path

    • Static resource paths can be configured

    • However, the access prefix of static resources cannot be configured. Otherwise, index.html cannot be accessed by default

      spring:
      #  mvc:
      #    static-path-pattern: /res/**   这个会导致welcome page功能失效
      
        web:
          resources:
            static-locations: classpath:/abc
      
  • controller can handle /index

2.3 CustomizationFavicon

favicon.ico can be placed in the static resource directory. (If the icon does not come out, clear the browser cache or close the browser and reopen it)

spring:
#  mvc:
#    static-path-pattern: /res/**   这个会导致 Favicon 功能失效

2.4 Principle of Static Resource Configuration

  • SpringBoot starts the default loading xxxAutoConfigurationclass (auto-configuration class)

  • The automatic configuration class of the SpringMVC function WebMvcAutoConfigurationtakes effect

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnWebApplication(
        type = Type.SERVLET
    )
    @ConditionalOnClass({
          
          Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
    @ConditionalOnMissingBean({
          
          WebMvcConfigurationSupport.class})
    @AutoConfigureOrder(-2147483638)
    @AutoConfigureAfter({
          
          DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
    public class WebMvcAutoConfiguration {
          
          }
    
  • What is in the container.

      @Configuration(
            proxyBeanMethods = false
        )
        @Import({
          
          WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
            @EnableConfigurationProperties({
          
          WebMvcProperties.class, WebProperties.class})
        @Order(0)
        public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
          
          }
    
  • The relevant properties of the configuration file are bound to xxx . WebMvcProperties== spring.mvc , WebProperties== spring.web

2.4.1 The configuration class has only one parameterized constructor

	//有参构造器所有参数的值都会从容器中确定
//WebProperties webProperties;获取和spring.web绑定的所有的值的对象
//WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象
//ListableBeanFactory beanFactory Spring的beanFactory
//HttpMessageConverters 找到所有的HttpMessageConverters
//ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。=========
//DispatcherServletPath  
//ServletRegistrationBean   给应用注册Servlet、Filter....
	 public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
    
    
            this.resourceProperties = webProperties.getResources();
            this.mvcProperties = mvcProperties;
            this.beanFactory = beanFactory;
            this.messageConvertersProvider = messageConvertersProvider;
            this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
            this.dispatcherServletPath = dispatcherServletPath;
            this.servletRegistrations = servletRegistrations;
            this.mvcProperties.checkConfiguration();
        }

2.4.2 Default Rules for Resource Handling

This is the default configuration rule for accessing static resources. After the static resource of jQuery is introduced, this prefix has been configured by default, and the static resource access path /webjars/**is also added./META-INF/resources/webjars/

 public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    
            if (!this.resourceProperties.isAddMappings()) {
    
    
                logger.debug("Default resource handling disabled");
            } else {
    
    
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
    
    
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (this.servletContext != null) {
    
    
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{
    
    resource});
                    }

                });
            }
        }

        private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
    
    
            this.addResourceHandler(registry, pattern, (registration) -> {
    
    
                registration.addResourceLocations(locations);
            });
        }

        private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, Consumer<ResourceHandlerRegistration> customizer) {
    
    
            if (!registry.hasMappingForPattern(pattern)) {
    
    
                ResourceHandlerRegistration registration = registry.addResourceHandler(new String[]{
    
    pattern});
                customizer.accept(registration);
                registration.setCachePeriod(this.getSeconds(this.resourceProperties.getCache().getPeriod()));
                registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
                registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
                this.customizeResourceHandlerRegistration(registration);
            }
        }
spring:
#  mvc:
#    static-path-pattern: /res/**

  resources:
    static-locations: classpath:/abc
    add-mappings: false   #禁用所有静态资源规则
@ConfigurationProperties("spring.web")
public class WebProperties {
    
    
    private Locale locale;
    private WebProperties.LocaleResolver localeResolver;
    private final WebProperties.Resources resources;

    public WebProperties() {
    
    
        this.localeResolver = WebProperties.LocaleResolver.ACCEPT_HEADER;
        this.resources = new WebProperties.Resources();
    }

    public Locale getLocale() {
    
    
        return this.locale;
    }

    public void setLocale(Locale locale) {
    
    
        this.locale = locale;
    }

    public WebProperties.LocaleResolver getLocaleResolver() {
    
    
        return this.localeResolver;
    }

    public void setLocaleResolver(WebProperties.LocaleResolver localeResolver) {
    
    
        this.localeResolver = localeResolver;
    }

    public WebProperties.Resources getResources() {
    
    
        return this.resources;
    }

    public static class Resources {
    
    
        private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{
    
    "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
        private String[] staticLocations;
        private boolean addMappings;
        private boolean customized;
        private final WebProperties.Resources.Chain chain;
        private final WebProperties.Resources.Cache cache;

        public Resources() {
    
    
            this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
            this.addMappings = true;
            this.customized = false;
            this.chain = new WebProperties.Resources.Chain();
            this.cache = new WebProperties.Resources.Cache();
        }

2.4.3 Processing rules of welcome page

// HandlerMapping:处理器映射。保存了每一个Handler能处理哪些请求。	

	  @Bean
        public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
    
    
            WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
            welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
            welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
            return welcomePageHandlerMapping;
        }
WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
    
    
        if (welcomePage != null && "/**".equals(staticPathPattern)) {
    
    
            //要用欢迎页功能,必须是/**
            logger.info("Adding welcome page: " + welcomePage);
            this.setRootViewName("forward:index.html");
        } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
    
    
            //调用Controller  /index
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");
        }
    }

2.4.4 favicon

The browser will send a /favicon request to obtain the icon, and it will not be obtained during the entire session

Guess you like

Origin blog.csdn.net/m0_46502538/article/details/121890589