Web 场景 1.web 开发简介 Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)
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 )).
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.
Custom Favicon
support (covered later in this document ).
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
2.静态资源规则与定制化 静态资源目录 只要静态资源放在类路径下: called /static
(or /public
or /resources
or /META-INF/resources
访问 : 当前项目根路径/ + 静态资源名 原理: 静态映射/**。
请求进来,先去找 Controller 看能不能处理。不能处理的所有请求又都交给静态资源处理器。静态资源也找不到则响应 404 页面。
也可以改变默认的静态资源路径,/static
,/public
,/resources
, /META-INF/resources
失效
1 2 3 4 spring: web: resources: static-locations: [classpath:/haha/ ]
静态资源访问前缀: 1 2 3 spring: mvc: static-path-pattern: /res/**
当前项目 + static-path-pattern + 静态资源名 = 静态资源文件夹下找
webjar 可用 jar 方式添加 css,js 等资源文件,
https://www.webjars.org/
例如,添加 jquery
1 2 3 4 5 <dependency > <groupId > org.webjars</groupId > <artifactId > jquery</artifactId > <version > 3.7.1</version > </dependency >
访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js 后面地址要按照依赖里面的包路径。
3. welcome 与 favicon 功能 官方文档
欢迎页支持 静态资源路径下 index.html。
可以配置静态资源路径 但是不可以配置静态资源的访问前缀。否则导致 index.html 不能被默认访问 1 2 3 4 5 6 spring: web: resources: static-locations: [classpath:/haha/ ]
自定义 Favicon 指网页标签上的小图标。
favicon.ico 放在静态资源目录下即可。
4.【源码分析】-静态资源原理 SpringBoot 启动默认加载 xxxAutoConfiguration 类(自动配置类) SpringMVC 功能的自动配置类WebMvcAutoConfiguration
,生效 1 2 3 4 5 6 7 8 9 10 @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 { ... }
给容器中配置的内容:
配置文件的相关属性的绑定:WebMvcProperties==spring.mvc 、ResourceProperties==spring.resources 1 2 3 4 5 6 7 @Configuration(proxyBeanMethods = false) @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer { ... }
配置类只有一个有参构造器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public WebMvcAutoConfigurationAdapter (WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) { this .mvcProperties = mvcProperties; this .beanFactory = beanFactory; this .messageConvertersProvider = messageConvertersProvider; this .resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable(); this .dispatcherServletPath = dispatcherServletPath; this .servletRegistrations = servletRegistrations; this .mvcProperties.checkConfiguration(); }
ResourceProperties resourceProperties;获取和 spring.resources 绑定的所有的值的对象 WebMvcProperties mvcProperties 获取和 spring.mvc 绑定的所有的值的对象 ListableBeanFactory beanFactory Spring 的 beanFactory HttpMessageConverters 找到所有的 HttpMessageConverters ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器。 DispatcherServletPath ServletRegistrationBean 给应用注册 Servlet、Filter…. 资源处理的默认规则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... public class WebMvcAutoConfiguration { ... public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { ... @Override protected void addResourceHandlers (ResourceHandlerRegistry registry) { super .addResourceHandlers(registry); if (!this .resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled" ); return ; } ServletContext servletContext = getServletContext(); addResourceHandler(registry, "/webjars/**" , "classpath:/META-INF/resources/webjars/" ); addResourceHandler(registry, this .mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this .resourceProperties.getStaticLocations()); if (servletContext != null ) { registration.addResourceLocations(new ServletContextResource (servletContext, SERVLET_LOCATION)); } }); } ... } ... }
根据上述代码,我们可以通过配置禁止所有静态资源规则。
1 2 3 4 spring: web: resources: add-mappings: false
静态资源规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 @ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties { private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/" , "classpath:/resources/" , "classpath:/static/" , "classpath:/public/" }; private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS; ... }
欢迎页的处理规则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ... public class WebMvcAutoConfiguration { ... public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware { ... @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
的构造方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) { if (welcomePage != null && "/**" .equals(staticPathPattern)) { logger.info("Adding welcome page: " + welcomePage); setRootViewName("forward:index.html" ); } else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { logger.info("Adding welcome page template: index" ); setRootViewName("index" ); } }
这构造方法内的代码也解释了web 场景-welcome 与 favicon 功能 中配置static-path-pattern
了,welcome 页面和小图标失效的问题。