spring-mvc-static.rar
《SpringBoot SpringMVC静态资源访问原理》

在 SpringBoot 中有自动配置类 WebMvcAutoConfigurationAdapter ,在自动配置类,注册了静态资源处理器 ResourceHttpRequestHandler,而该静态资源支持四大目录的资源读取,分别是

classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/

同样读取顺序也如上。

使用 SpringBoot 默认提供的静态资源配置,很被动,首先就是请求路径的问题,在配置中,请求路径为 "/" + "静态资源目录名称" + "资源文件名" 进行访问,

如果我们想要实现 "/定义路径" + "静态资源目录名称" + "资源文件名" 的方式,就需要自己配置 ResourceHttpRequestHandler

在来回顾下 SpringBoot 中 MVC 的自动配置类 WebMvcAutoConfigurationAdapter 部分信息,如下
01.png
在图中有 Order(0) ,表示该配置类的优先级, order越小加载优先级越高,所以我们自定义的配置会晚于 springBoot 默认的加载优先级。

在 Spring MVC 中 Handler的存储是以 key-value 的形式进行存储, key-表示的请求 urlvalue 就是处理的 Handler,例如:针对 Spring Boot 默认的配置类存储的 key-value 就结构如下:

`/ -> ResourceHttpRequestHandler`** 。

结合加载顺序,可以特出一个结论:如果我们自定了新的 ResourceHttpRequestHandler 且,请求的url前缀也为 /** ,由于我们的配置晚于SpringBOot 自动配置,所以我们的配置会覆盖自动配置的数据。反之,如果自定义的
ResourceHttpRequestHandler 对应的url前缀不为 /** 自然不会覆盖 SpringBoot 自动配置的四个静态资源路径。

一个简单的实验:自定义静态资源路径,同时指定url前缀为 /** 测试是否覆盖SpringBoot默认配置

代码结构如下:
02.png
其中 classpath:/myself 是自定义的静态资源路径,并且自定义静态资源路径只有这一个,所有 SpringBoot 默认的静态资源路径因此失效,

相关的配置信息在 WebMvcConfig 中,配置内容如下
04.png

直接在浏览器访问,我们自定义的静态资源,以及请求旧有的资源路径,结果如下
05.png
同样的我们可以通过 debug 的方式来看一下,请求处理操作中,执行处理的 ResourceHttpRequestHandler,如下图:
06.png

一个简单的实验:自定义静态资源路径,同时指定url前缀 /myself/** ,测试SpringBoot 默认的四个静态资源路径仍然生效

项目结构不变如下:
07.png
配置类 WebMvcConfig 如下
03.png

启动项目,通过浏览器访问测试,测试结果如下
08.png
测试结果意料中,所有的静态资源都能访问,

下面通过 debug 看一下相关的处理 Handler,如下图:
09.png

一个有趣的实验

资源前缀 /** 下存在一个资源文件夹 myself/ 文件,同时该文件路径下有一个 myself.html 文件

资源前缀/myself/** 下存在一个资源文件 ‘myself.html’ 文件

此时:两者的访问路径都是 ‘/myself/myself.html’ ,那究竟是以哪个路径下的资源为主??

再来回顾上一个实现的debug 截图,如下:
09.png

如图,处理的顺序是: /** 的资源先处理,然后处理 /myself/** 下的资源路径

通过代码可以知道 /** 所对应的资源路径,也就是 SpringBoot 默认配置的四个资源路径 classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,’classpath:/public/‘ 下的资源优先加载

按理说,应该会加载 /** 下的资源路径,不过结果却相反,因为在代码处理中,SpringMvc 会匹配到两个符合条件的处理,一个是 /** 一个是 /myself/** ,SpringMVC 会选择一个最优的处理,而这个最后的处理就是 /myself/**

所以前缀匹配的越多,则以响应的 Handler 处理器进行执行,来简单看一下最优处理的相关代码,如下图:
10.png
所以前缀的匹配的越多,就用哪个对应的 Handler 处理器进行处理