SpringBoot静态资源管理和装配

发布于:2025-02-11 ⋅ 阅读:(40) ⋅ 点赞:(0)

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/"