SpringBoot的靜態資源處理


測試

1、靜態資源訪問

官網說明如下:

默認情況下,Spring Boot 從 Classpath 中名為/static(或/public/resources/META-INF/resources)的目錄或ServletContext的根目錄中提供靜態內容。它使用 Spring MVC 中的ResourceHttpRequestHandler,因此您可以通過添加自己的WebMvcConfigurer並覆蓋addResourceHandlers方法來修改該行為。

在獨立的 Web 應用程序中,還啟用了容器中的默認 servlet,並將其用作后備,如果 Spring 決定不處理ServletContext的根,則從ServletContext的根開始提供內容。在大多數情況下,這不會發生(除非您修改默認的 MVC 配置),因為 Spring 始終可以通過DispatcherServlet處理請求。

默認情況下,資源 Map 在/**上,但是您可以使用spring.mvc.static-path-pattern屬性對其進行調整。例如,將所有資源重定位到/resources/**可以實現如下:

spring.mvc.static-path-pattern=/resources/**

您還可以使用spring.resources.static-locations屬性來自定義靜態資源位置(用目錄位置列表替換默認值)。根 Servlet 上下文路徑"/"也會自動添加為位置。

除了前面提到的“標准”靜態資源位置以外,還對Webjars content進行了特殊處理。如果 jar 文件以 Webjars 格式打包,則從 jar 文件提供帶有/webjars/**路徑的任何資源。

如果您的應用程序打包為 jar,則不要使用src/main/webapp目錄。盡管此目錄是一個通用標准,但它僅在 war 打包中有效,並且在生成 jar 時,大多數構建工具都將其忽略。

Spring Boot 還支持 Spring MVC 提供的高級資源處理功能,允許使用案例,例如緩存清除靜態資源或對 Webjars 使用版本無關的 URL。

要對 Webjar 使用版本無關的 URL,請添加webjars-locator-core依賴項。然后聲明您的 Webjar。以 jQuery 為例,在"/webjars/jquery/x.y.z/jquery.min.js"中添加"/webjars/jquery/jquery.min.js"結果。其中x.y.z是 Webjar 版本。

進行測試:

靜態資源目錄

image-20210309222539476

進行測試的時候,由於之前項目引入了手寫的sarter,里面有個攔截器,對所有資源進行攔截,導致訪問不到靜態資源,需要方向。

image-20210309222653020

由於靜態資源默認的映射是/**,為了方便攔截器放行,這里可以自定義。

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

官網也說明了,可以自定義靜態資源路徑

spring:
  mvc:
    static-path-pattern: /res/**   ##這里是加的請求的路徑
  resources:
    static-locations: [classpath:/test/]  ## 這里是隱射的路徑
image-20210309223917217

注意,這里數組只寫一個的話,會把其他幾個路徑覆蓋掉。

webjar

      <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.5.1</version>
        </dependency>

image-20210309224235934

進行測試

http://localhost:8888/webjars/jquery/3.5.1/webjars-requirejs.js

2、歡迎頁支持

  • 靜態資源路徑下 index.html

    • 可以配置靜態資源路徑
    • 但是不可以配置靜態資源的訪問前綴。否則導致 index.html不能被默

image-20210309225953756

要注釋掉下面配置,因為在源碼中,有了判斷,不然不生效

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

3、自定義 Favicon

favicon.ico 放在靜態資源目錄下即可。

image-20210310133507481

源碼

  • 因為springboot自動配置的原因,引入了很多自動配置類,所以先找到入口WebMvcAutoConfigurationimage-20210309233224925

  • 查看這個配置類生效的前提條件,其中發現了 WebMvcConfigurationSupport.class.

    @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 {
    

    如果自己全部接管mvc的,可以使用@EnableWebMvc這個注解,它其實會往IOC容器注入DelegatingWebMvcConfiguration,它繼承了WebMvcConfigurationSupport。

  • 都是在容器中找WebMvcAutoConfigurationAdapter這個類

    //有參構造器所有參數的值都會從容器中確定
    //ResourceProperties resourceProperties;獲取和spring.resources綁定的所有的值的對象
    //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<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();
    		}
    

資源處理的默認規則

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
			super.addResourceHandlers(registry);
            //如果在yaml里面配置的false,則靜態資源全部失效
			if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
			ServletContext servletContext = getServletContext();
            //這里配置的就是webjars資源映射
			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));
				}
			});
		}

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

		private void addResourceHandler(ResourceHandlerRegistry registry, String pattern,
				Consumer<ResourceHandlerRegistration> customizer) {
			if (registry.hasMappingForPattern(pattern)) {
				return;
			}
			ResourceHandlerRegistration registration = registry.addResourceHandler(pattern);
			customizer.accept(registration);
			registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
			registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
			customizeResourceHandlerRegistration(registration);
		}

image-20210310134321545

image-20210310134420044

注:如果請求的靜態資源和請求的接口是同一個路徑,則優先處理接口

3、歡迎頁的處理規則

		@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, 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");
		}
	}

image-20210310133939693

注:如果這里配置了靜態資源路徑,會導致歡迎頁失效,如果沒有失效,則請重定向到Index.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM