SpringBoot静态资源管理和装配:WebMvcAutoConfiguration
SpringBoot通过WebMvcAutoConfiguration.class自动装配类,来进行静态资源的装配
@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 {
......
}
视图解析器
其中包括两种视图解析器的bean装配
@Bean
@ConditionalOnBean({View.class})
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
BeanNameViewResolver resolver = new BeanNameViewResolver();
resolver.setOrder(2147483637);
return resolver;
}
@Bean
@ConditionalOnBean({ViewResolver.class})
@ConditionalOnMissingBean(
name = {"viewResolver"},
value = {ContentNegotiatingViewResolver.class}
)
public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) {
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager((ContentNegotiationManager)beanFactory.getBean(ContentNegotiationManager.class));
resolver.setOrder(Integer.MIN_VALUE);
return resolver;
}
格式化器FormatterRegistry
@Bean
public FormattingConversionService mvcConversionService() {
WebMvcProperties.Format format = this.mvcProperties.getFormat();
WebConversionService conversionService = new WebConversionService((new DateTimeFormatters()).dateFormat(format.getDate()).timeFormat(format.getTime()).dateTimeFormat(format.getDateTime()));
this.addFormatters(conversionService);
return conversionService;
}
消息转换器messageConvertersProvider
public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
this.resourceProperties = webProperties.getResources();
this.mvcProperties = mvcProperties;
this.beanFactory = beanFactory;
this.messageConvertersProvider = messageConvertersProvider;
this.resourceHandlerRegistrationCustomizer = (ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
this.dispatcherServletPath = dispatcherServletPath;
this.servletRegistrations = servletRegistrations;
this.mvcProperties.checkConfiguration();
}
欢迎界面映射
@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;
}
静态资源处理器(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});
}
});
}
}
这个方法调用了两个重载的addResourceHandler方法,第一个加载了前端js的依赖(webjars的方式,localhost:8080/webjars/jquery/3.3.1/jquery.js);第二个是导入静态资源路径下的资源
第一个addResourceHandler方法:引入webjars
// pattern是"/webjars/**",locations是"classpath:/META-INF/resources/webjars/"
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern, String... locations) {
this.addResourceHandler(registry, pattern, (registration) -> {
registration.addResourceLocations(locations);
});
}
<!‐‐引入jquery‐webjar‐‐>在访问的时候只需要写webjars下面资源的名称即可
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1</version></dependency>
</dependencied>
这个jar包包含了jquery的类库等,以jar包的方式引入,不需要再用传统前端的方式引入
可以直接路径访问:localhost:8080/webjars/jquery/3.3.1/jquery.js
所有 /webjars/**,都去 classpath:/META-INF/resources/webjars/ 找资源;
webjars:以jar包的方式引入静态资源;http://www.webjars.org/
引入之后,thymeleaf引用这个js文件的方式:
使用th:src
<script th:src="@{/webjars/jquery/3.3.1/jquery.js}"/>
第二个addResourceHandler方法:读取配置文件或者配置类的静态资源路径值,然后引入路径下的静态资源
// pattern:this.mvcProperties.getStaticPathPattern(),
/* customizer:匿名内部类: (registration) -> {
// 读取静态资源位置url,然后添加到资源属性类中
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
// 项目路径不是空的话,要给资源的访问路径加上项目自定义访问路径才能访问到;反之,则直接localhost:8080/static/111.img就可以
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
}*/
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);
}
}
这里读取的pattern还有static-location都可以从application.yaml中配置
spring:
web:
resources:
static-locations: classpath:/templates, classpath:/static, classpath:/public, classpath:/resources, classpath:/META-INF/resources
mvc:
view:
prefix: classpath:/templates/
suffix: .html
static-path-pattern: /**
static-path-pattern表示指定路径下的所有静态资源都可以访问
而static-locations默认是包含4个值:
"classpath:/META‐INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"