spring-mvc-static.rar
《SpringBoot SpringMVC静态资源访问原理》
在 SpringBoot 中有自动配置类 WebMvcAutoConfigurationAdapter
,在自动配置类,注册了静态资源处理器 ResourceHttpRequestHandler
,而该静态资源支持四大目录的资源读取,分别是
classpath:/META-INF/resources/
,classpath:/resources/
,classpath:/static/
,classpath:/public/
同样读取顺序也如上。
使用 SpringBoot 默认提供的静态资源配置,很被动,首先就是请求路径的问题,在配置中,请求路径为 "/"
+
"静态资源目录名称"
+
"资源文件名"
进行访问,
如果我们想要实现 "/定义路径"
+
"静态资源目录名称"
+
"资源文件名"
的方式,就需要自己配置 ResourceHttpRequestHandler
在来回顾下 SpringBoot 中 MVC 的自动配置类 WebMvcAutoConfigurationAdapter
部分信息,如下
在图中有 Order(0)
,表示该配置类的优先级, order越小加载优先级越高,所以我们自定义的配置会晚于 springBoot 默认的加载优先级。
在 Spring MVC 中 Handler的存储是以 key-value
的形式进行存储, key-表示的请求 url
,value 就是处理的 Handler
,例如:针对 Spring Boot 默认的配置类存储的 key-value
就结构如下:
`/ -> ResourceHttpRequestHandler`** 。
结合加载顺序,可以特出一个结论:如果我们自定了新的 ResourceHttpRequestHandler
且,请求的url前缀也为 /**
,由于我们的配置晚于SpringBOot 自动配置,所以我们的配置会覆盖自动配置的数据。反之,如果自定义的ResourceHttpRequestHandler
对应的url前缀不为 /**
自然不会覆盖 SpringBoot 自动配置的四个静态资源路径。
一个简单的实验:自定义静态资源路径,同时指定url前缀为 /**
测试是否覆盖SpringBoot默认配置
代码结构如下:
其中 classpath:/myself
是自定义的静态资源路径,并且自定义静态资源路径只有这一个,所有 SpringBoot 默认的静态资源路径因此失效,
相关的配置信息在 WebMvcConfig
中,配置内容如下
直接在浏览器访问,我们自定义的静态资源,以及请求旧有的资源路径,结果如下
同样的我们可以通过 debug 的方式来看一下,请求处理操作中,执行处理的 ResourceHttpRequestHandler
,如下图:
一个简单的实验:自定义静态资源路径,同时指定url前缀 /myself/**
,测试SpringBoot 默认的四个静态资源路径仍然生效
项目结构不变如下:
配置类 WebMvcConfig
如下
启动项目,通过浏览器访问测试,测试结果如下
测试结果意料中,所有的静态资源都能访问,
下面通过 debug 看一下相关的处理 Handler,如下图:
一个有趣的实验
资源前缀 /**
下存在一个资源文件夹 myself/
文件,同时该文件路径下有一个 myself.html
文件
资源前缀/myself/**
下存在一个资源文件 ‘myself.html’ 文件
此时:两者的访问路径都是 ‘/myself/myself.html’ ,那究竟是以哪个路径下的资源为主??
再来回顾上一个实现的debug 截图,如下:
如图,处理的顺序是: /**
的资源先处理,然后处理 /myself/**
下的资源路径
通过代码可以知道 /**
所对应的资源路径,也就是 SpringBoot 默认配置的四个资源路径 classpath:/META-INF/resources/
,classpath:/resources/
,classpath:/static/
,’classpath:/public/‘ 下的资源优先加载
按理说,应该会加载 /**
下的资源路径,不过结果却相反,因为在代码处理中,SpringMvc 会匹配到两个符合条件的处理,一个是 /**
一个是 /myself/**
,SpringMVC 会选择一个最优的处理,而这个最后的处理就是 /myself/**
所以前缀匹配的越多,则以响应的 Handler 处理器进行执行,来简单看一下最优处理的相关代码,如下图:
所以前缀的匹配的越多,就用哪个对应的 Handler 处理器进行处理