• 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

  • 相关阅读:
    二分 || UOJ 148 跳石头
    等边n边型
    激光样式
    n个数中选k个数和为sum
    引爆炸弹
    光盘行动
    (二分)分蛋糕问题
    总结
    个人测试
    第三次团队作业
  • 原文地址:https://www.cnblogs.com/dalianpai/p/14518137.html
Copyright © 2020-2023  润新知