SpringBoot2-6 Web1-静态资源 默认4个目录,特别是resources 目录, webjars引入和内部资源访问,注意其内部resources目录 HandlerMapping

本文详细介绍了Spring Boot中关于Web的配置,包括静态资源目录、访问路径、WebJars的使用以及欢迎页的设置。讲解了如何配置静态资源路径、访问前缀,以及如何处理静态资源和WebJars资源的访问。同时,探讨了Spring Boot的WelcomePageHandlerMapping的工作原理和静态资源的缓存策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Web

帮助文档中专列了一个web目录

springboot是框架的框架,实现web仍然是spring mvc

   创建一个web项目--基于java8   

 删除没用的

 静态资源目录

/static (or /public or /resources or /META-INF/resources)

指的是类根目录下以下4个文件夹

各方一张图片,之后重启,输入http://localhost:8080/3.png

即可访问

 也就是使用  项目根路径+静态资源名

访问原理   /**

   1)请求进来,优先找contoller看看有没有同名的,所有不能处理的再去找静态资源

                           静态资源就会上面4个目录去找,找不到返回404

      静态资源访问前缀

        默认无前缀,但是/**会导致未来配拦截器把静态资源也拦截了,所以要指定放行路径,也就是要给静态资源配置访问前缀

      

变成了如下

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

 静态资源的路径也可以改变

You can also customize the static resource locations by using the spring.web.resources.static-locations property (replacing the default values with a list of directory locations). The root servlet context path, "/", is automatically added as a location as well.

yaml配置

classpath:/allimage

  classpath代表类目录下也就是resources目录下

也支持配数组   static-locations: [classpath:/allimage]
spring:
  mvc:
    static-path-pattern: "/res/**"
  web:
        resources:
          static-locations: classpath:/allimage

 即只有该目录是静态资源默认目录

Webjars-了解

     就是把很多常见的bootstrap,jquery做成jar包当成依赖引入

WebJars - Web Libraries in Jars

引入jquery依赖

<dependency>
    <groupId>org.webjars.npm</groupId>
    <artifactId>github-com-jquery-jquery</artifactId>
    <version>3.6.0</version>
</dependency>

 maven刷新之后,lib会出现jquey jar包 

展开发现,其也是把静态资源放在resource下的 

In addition to the “standard” static resource locations mentioned earlier, a special case is made for Webjars content. Any resources with a path in /webjars/** are served from jar files if they are packaged in the Webjars format.

就是说访问jar里面的资源,要通过  /webjars/** 来实现 

也就是默认的resources/webjars是最上层目录,github-com-jquery-jquery是第二层,3.6.0是第三层

静态访问路径是    http://localhost:8080/webjars/github-com-jquery-jquery/3.6.0/jquery.js

还可以访问其他的什么  http://localhost:8080/webjars/github-com-jquery-jquery/3.6.0/index.html

截图证明一下

 欢迎页

   

https://docs.spring.io/spring-boot/docs/2.7.8-SNAPSHOT/reference/html/web.html#web.servlet.spring-mvc.favicon

 Welcome Page

Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in the configured static content locations. If one is not found, it then looks for an index template. If either is found, it is automatically used as the welcome page of the application.

两种方法:1种是写一个静态页面,另外一种在controller里面拦截/index,然后使用静态模板

第一种:放一个index.html到静态目录下

   

    前提是你得只注释掉 static-path-pattern

     

 

图标

每个网站都有自己的图标,一般命名为 favicon.ico,看一下百度的,可以在右面搜索

 As with other static resources, Spring Boot checks for a favicon.ico in the configured static content locations. If such a file is present, it is automatically used as the favicon of the application.

也就是名字一定要叫favicon.ico

 重启,并没有出现这个图标,原因浏览器没关就算同一次会话

换个浏览器就出来了

同样不能更改默认静态目录

静态资源访问原理

WebMvcAutoConfiguration生效判断

springboot加载时会加载很多xxxAutoConfiguration类

web配置主要集中在   WebMvcAutoConfiguration,如下方法查找

 

 

 

 看它是否生效

@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})

type要是sevlet,我们不是响应式,那么就是servlet

第二个条件三个类容器中也是有的

 

 

 第三个条件需要没有WebMvcConfigurationSupport这个组件,但是我们有

 因为第三个条件没有满足WebMvcAutoConfiguration里面的内容应该没有生效

WebMvcAutoConfiguration生效后给容器中增加

1)public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter()

       OrderedHiddenHttpMethodFilter兼容Rest风格所用,支持单提交,put  delete等操作

2)  OrderedFormContentFilter  表单内容过滤器

3)WebMvcAutoConfigurationAdapter

其上标记了

@Configuration所以是个配置类

注意  这句话  

@EnableConfigurationProperties({WebMvcProperties.class, WebProperties.class})

表示配置文件的相关属性和XX进行了绑定

 

1)WebMvcProperties     

       进入该类,其跟property或yml配置文件中prefix = "spring.mvc"绑定

 

2)WebProperties跟
@ConfigurationProperties("spring.web") 绑定

WebMvcAutoConfigurationAdapter-开始

只有1个有参构造器,那么其所有参数的值都要从容器中找到

 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();
        }

 

参数1:WebProperties webProperties就是来自于绑定文件WebProperties.class指向配置

              @ConfigurationProperties("spring.web")所有值对象

参数2:WebMvcProperties mvcProperties来自于绑定WebMvcProperties.class指向配置

           prefix = "spring.mvc"所生成对象

参数3: ListableBeanFactory beanFactory相当于找Spring bean工厂,就是我们的容器

参数4:ObjectProvider<HttpMessageConverters> messageConvertersProvider, 

             找到所有的HttpMessageConverter
参数5ObjectProvider<ResourceHandlerRegistrationCustomizer>

resourceHandlerRegistrationCustomizerProvider,

      找到资源处理器的自定义器
 参数6:ObjectProvider<DispatcherServletPath> dispatcherServletPath,
 参数7: ObjectProvider<ServletRegistrationBean<?>> servletRegistrations

            用于给应用注册原生的servlet ,listener等

继续查看addResourceHandlers,发现资源处理的默认规则:

   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});
                    }

                });
            }
        }

     打上断点,因为属于配置类,所以启动就配好

if (!this.resourceProperties.isAddMappings())

this.addMappings默认为true,如果配置文件没有修改
 public Resources() {
            this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
            this.addMappings = true;
            this.customized = false;
            this.chain = new Chain();
            this.cache = new Cache();
        }

 禁用所有静态资源默认配置

 可以修改application.yaml,把addMappings(可以写为add-maapings)变成false,那么静态资源配置就都失效了

spring:
#  mvc:
#    static-path-pattern: "/res/**"
   web:
     resources:
       add-mappings: false

##          static-locations: classpath:/allimage
#        static-locations: [classpath:/allimage]

再重启访问首页

 再改回去

使用默认配置addMappings默认为true

1)缓存----从新的addResourceHandlers方法中看不出来,仅供参考

yaml

spring:
#  mvc:
#    static-path-pattern: "/res/**"
   web:
     resources:
#       add-mappings: false

##          static-locations: classpath:/allimage
#        static-locations: [classpath:/allimage]
        cache:
          period: 11000

进入period查看缓存时间单位,缓存意思就是浏览器默认存储静态资源多久不用更新

@DurationUnit(ChronoUnit.SECONDS)

c

 Debug运行

 

2)继续执行断点-webjar

     

 this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");

本句意思为注册/webjars所有请求,按照各个jar包resources:/META-INF/resources/webjars这个路径寻找,比如找到之前距离的jquery:

   

 验证:

   访问

 

 去除禁用缓存以及filter,可以看到如下位置 Name下出现了文件 

 

可以看到第二次访问  status 304

如果客户端发送了一个带条件的GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。简单的表达就是:服务端已经执行了GET,但文件未变化。

没有找到以下

3)继续执行断点-默认静态资源路径

        类似于webjar

                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());

 这里也先使用了getStaticPathPattern() ,返回

  

其次  getStaticLocations()

进入其类,发现

再进入发现常量CLASSPATH_RESOURCE_LOCATIONS,发现了这四个位置

{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

 public static class Resources {
        private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
        private String[] staticLocations;
        private boolean addMappings;
        private boolean customized;
        private final Chain chain;
        private final Cache cache;

 静态资源都有缓存策略,此处未验证

------------------------------WebMvcAutoConfigurationAdapter-结束-------------------------

WelcomePageHandlerMapping

先介绍Handler Mapping.:   SpringMVC核心组件,处理器映射,里面保存了每一个handler能处理哪些请求,然后利用反射调用handler

@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;
        }

进入到new WelcomePageHandlerMapping

 

WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
        if (welcomePage != null && "/**".equals(staticPathPattern)) {
            logger.info("Adding welcome page: " + welcomePage);
            this.setRootViewName("forward:index.html");
        } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");
        }
staticPathPattern是我们在yaml中配置的

 在这里打个断点

断点运行, 鼠标放到welcomePage会提示当前获得

  

 如果更改了yaml中  ,比如变成

static-path-pattern: "/res/**"

并且把index.html从4个路径中拿走,挪到/res下也是不行的,因为只会在标准地方找

也就是说无论是否指定 static-path-pattern,index.html都应该放在4个路径下

那么就会找不到

 

 如果不存在,则进入 controller去找

} else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i7i8i9com

创业创新像大树那样给更多人乘凉

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值