SpringBoot(04) -- Web开发-- 自动配置概述

SpringBoot2学习笔记

源码地址

四、Web开发

4.1)SpringMVC自动配置概述

我们都无需自定义配置)

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

Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

  • 内容协商视图解析器和BeanName视图解析器

Support for serving static resources, including support for WebJars (covered later in this document)).

  • 静态资源(包括webjars)

Automatic registration of Converter, GenericConverter, and Formatter beans.

  • 自动注册 Converter,GenericConverter,Formatter

Support for HttpMessageConverters (covered later in this document).

  • 支持 HttpMessageConverters (后来我们配合内容协商理解原理)

Automatic registration of MessageCodesResolver (covered later in this document).

  • 自动注册 MessageCodesResolver (国际化用)

Static index.html support.

  • 静态index.html 页支持

Custom Favicon support (covered later in this document).

  • 自定义 Favicon

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

  • 自动使用 ConfigurableWebBindingInitializer ,(DataBinder负责将请求数据绑定到JavaBean上)

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.

不用@EnableWebMvc注解。使用 **@Configuration** + **WebMvcConfigurer** 自定义规则

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.

声明 **WebMvcRegistrations** 改变默认底层组件

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.

使用 **@EnableWebMvc+@Configuration+DelegatingWebMvcConfiguration 全面接管SpringMVC**

4.2)简单功能分析

4.2.1)静态资源访问

4.2.1.1)静态资源目录

只要静态资源放在类路径下: called /static (or /public or /resources or /META-INF/resources

访问 : 当前项目根路径/ + 静态资源名

示例:工程中新建相应的文件夹,目录如下图

 浏览器访问:

  1. http://localhost:8080/metainf.jpg,图片如下:

  1. http://localhost:8080/public.gif,图片如下:

 http://localhost:8080/resources.jpg,图片如下:

 http://localhost:8080/public.gifhttp://localhost:8080/static.png,图片如下:

原理: 静态映射/**,拦截所以请求;请求进来,先去找Controller看能不能处理;不能处理的所有请求又都交给静态资源处理器;静态资源也找不到则响应404页面

新建 HelloController.java,代码如下:

@RestController
public class HelloController {
​
    @RequestMapping("/metainf.jpg")
    public String hello(){
        return "aaaa";
    }
}

浏览器访问:http://localhost:8080/metainf.jpg,图片如下:

 改变默认的静态资源路径

4.2.2)静态资源访问前缀

默认无前缀,application.yaml,代码如下:

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

当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找

浏览器访问:http://localhost:8080/resources.jpg,页面报错,访问:http://localhost:8080/res/resources.jpg,页面可以正常访问,如下图:

 4.2.2.1)改变默认的静态资源路径

修改配置文件application.yaml,代码如下:

spring:
  mvc:
    # 静态资源访问默认无前缀
    static-path-pattern: /res/**
  resources:
    # 改变默认的静态资源路径
    static-locations: [classpath:/abc/]

浏览器访问:http://localhost:8080/resources.jpg,页面报错,访问:http://localhost:8080/res/abc.jpg,页面可以正常访问,如下图:

 4.2.3)欢迎页支持

  1. 静态资源路径下 index.html

  • 可以配置静态资源路径

  • 但是不可以配置静态资源的访问前缀。否则导致 index.html不能被默认访问

清空配置文件application.yaml,不使用额外配置【配置访问前缀会导致welcome page功能失效】,在resource目录下新建首页index.html,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>SpringBoot,欢迎您</h1>
<br>
</body>
</html>

浏览器访问默认地址:http://localhost:8080/,页面如下图:

 4.2.4)自定义 Favicon

自定义网页图标,favicon.ico 放在静态资源目录下即可,放到static目录下,浏览器访问默认地址:http://localhost:8080/,页面如下图:【配置访问前缀会导致自定义 Favicon功能失效】

 4.2.5)静态资源配置原理

  • SpringBoot启动默认加载 xxxAutoConfiguration 类(自动配置类)

  • SpringMVC功能的自动配置类 WebMvcAutoConfiguration,通过它实现资源配置,源码如下:

@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 {
    public static final String DEFAULT_PREFIX = "";
    public static final String DEFAULT_SUFFIX = "";
    private static final String[] SERVLET_LOCATIONS = new String[]{"/"};
​
    public WebMvcAutoConfiguration() {
    }
    ...
}

4.2.5.1)配置类只有一个有参构造器

给容器中配置内容:WebMvcAutoConfigurationAdapter方法,配置文件的相关属性和xxx进行了绑定。WebMvcProperties==spring.mvc、ResourceProperties==spring.resources,源码如下:

@ConfigurationProperties(
    prefix = "spring.mvc"
)
public class WebMvcProperties {
    private org.springframework.validation.DefaultMessageCodesResolver.Format messageCodesResolverFormat;
    ...
}
​
——————————————————————————————————————————————————————————————————
@ConfigurationProperties(
    prefix = "spring.resources",
    ignoreUnknownFields = false
)
public class ResourceProperties {
    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 final ResourceProperties.Chain chain;
    private final ResourceProperties.Cache cache;
        ...
}

有参构造器所有参数的值都会从容器中确定:

  • ResourceProperties resourceProperties:获取和spring.resources绑定的所有的值的对象

  • WebMvcProperties mvcProperties :获取和spring.mvc绑定的所有的值的对象

  • ListableBeanFactory beanFactory :Spring的beanFactory

  • HttpMessageConverters: 找到所有的HttpMessageConverters

  • ResourceHandlerRegistrationCustomizer :找到资源处理器的自定义器

  • ServletRegistrationBean : 给应用注册Servlet、Filter....

WebMvcAutoConfigurationAdapter方法,源码如下:

 @Configuration(
        proxyBeanMethods = false
    )
    @Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
    @EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class})
    @Order(0)
    public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
        private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class);
        private final ResourceProperties resourceProperties;
        private final WebMvcProperties mvcProperties;
        private final ListableBeanFactory beanFactory;
        private final ObjectProvider<HttpMessageConverters> messageConvertersProvider;
        private final ObjectProvider<DispatcherServletPath> dispatcherServletPath;
        private final ObjectProvider<ServletRegistrationBean<?>> servletRegistrations;
        final WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer;
​
        public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
            this.resourceProperties = resourceProperties;
            this.mvcProperties = mvcProperties;
            this.beanFactory = beanFactory;
            this.messageConvertersProvider = messageConvertersProvider;
            this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
            this.dispatcherServletPath = dispatcherServletPath;
            this.servletRegistrations = servletRegistrations;
        }
    ...
}

在配置文件application.yaml中可以设置禁用静态资源,代码如下:

spring:
  mvc:
    static-path-pattern: /res/**
​
  resources:
    # 禁用所有静态资源规则
    add-mappings: false 

4.2.5.2)欢迎页的处理规则

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

WelcomePageHandlerMapping,源码如下

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

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/125113621