Bootstrap

关于SpringMVC访问静态资源的一些个人见解

原创不易,转载请联系作者。 

   昨晚临回宿舍之前遇到一个访问静态资源路径的问题,研究了一会儿,没有研究出来。今天一早打开电脑,屏幕是昨天遗留的问题,越看越想解决它,要不然心里很不舒服。没想到这一深入研究,挖掘出以前许多和这相关但没注意的知识,结果陷入进去了,本来是一个问题,但逐渐转变成一小块知识的问题,就这样逐渐摸索和排盲,白天的时间很快过去了,虽然感觉自己离最终的答案很近了,可还是没有一个很清晰的严密回答。晚饭回来,继续研究,直至写这篇博文之前,终于搞懂了来龙去脉,特此记录一下,希望能帮助遇到类似问题的道友,能尽快地解决问题,在有限的时间内去学习更多的知识。

 

道友们别急,首先我把整个项目的文件架构列出来,具体问题要根据图中的内容才能指出。

项目目录:

                                                                                                   图一

web.xml 中的部分配置

                                                                                                     图二

spring-web.xml部分配置文件

                                                                                                    图三

controller文件

                                                                                                  图四

shopoperation.html文件

                                                                                              图五

现在我要在WEB-INF中的shopoperartion.html文件中引用webapp目录下resources目录下的common.js文件。如图五所示,我的src目录写的是

src='../resources/js/common/common.js'

这样写之后就能正确的引用到webapp目录下resources目录下的common.js文件。

我的问题就来了,

以前有时候我记得只要在src里面写要被引用文件的相对路径即可(相对路径和绝对路径不懂的同学可以百度一下)。

common.js在整个项目中的相对路径为     resources/js/common/common.js。按照我以前的理解就是下面所写,

src='resources/js/common/common.js'

也能访问到webapp目录下resources目录下的common.js文件。可结果是没有访问到。我就产生问题了,为什么在这里加一个../ 即上一层目录就能返回正确的答案?这里面到底是什么原因?

我做了一个实验,加../ 发现common.js的请求路径为:

                                                                                                  图六

不加../ 发现common.js的请求路径为:

                                                                                                 图七

细心的道友们可以发现多了图七比图六多了一个/shopdamin目录,所以没有访问到静态资源js。

在继续分析讲解直接,我先问道友们一个问题,有没有人能准确地讲出servlet的url-pattern匹配规则?一开始我一脸懵逼,以前只知道用,没有仔细研究过,这里给大家推荐一篇博文,给道友们涨涨知识:servlet的url-pattern匹配规则

里面主要说servlet的url-pattern大概主要有四种规则

1 精确匹配   <url-pattern>中配置的项必须与url完全精确匹配。

2 路径匹配   以“/”字符开头,并以“/*”结尾的字符串用于路径匹配

3 扩展名匹配  以“*.”开头的字符串被用于扩展名匹配

4 缺省匹配  ''/''

匹配顺序依次递减

1、精确匹配,servlet-mapping1:<url-pattern>/user/users.html</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配

2、路径匹配,先最长路径匹配,再最短路径匹配servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>/*</url-pattern>。当一个请求http://localhost:8080/appDemo/user/users.html来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配

3、扩展名匹配,servlet-mapping1:<url-pattern>/user/*</url-pattern>,servlet-mapping2:<url-pattern>*.action</url-pattern>。当一个请求http://localhost:8080/appDemo/user/addUser.action来的时候,servlet-mapping1匹配到,不再用servlet-mapping2匹配

4、缺省匹配,以上都找不到servlet,就用默认的servlet,配置为<url-pattern>/</url-pattern>

在图二中,我这里只定义了缺省拦截,也就是等级最低的一种,而在图三中为静态资源地访问定义了一种路径拦截,它的拦截等级是高于缺省拦截的。

下面继续讲解:

我这里给道友们捋一下 src加了../的 整个shopoperation.html 正确的访问过程。

首先在浏览器地址栏中输入http://localhost:8080/o2o/shopadmin/shopoperation  ,我们的配置文件中没有专门为这个路径配置过拦截,因此,我们通过图二的缺省拦截进行拦截,再通过图四配置,找到shopoperation.html。翻译一下:shopoperation.html真实的访问路径其实可以理解为:

 http://localhost:8080/o2o/shopadmin/WEB-INF/html/shopoperation.html (看图三前后缀配置,当然这这只能通过后台转发,访问WEB-INF文件),大伙儿注意shopoperation.html文件其实是在WEB-INF目录下的,这后面要提到。

接着,在加载shopoperation.html后,如图五所示,由于在shopoperation.html中需要引用webapp目录下resources目录下的common.js文件,根据src中的地址 src='../resources/js/common/common.js',这里重新再次发出请求。重点来了,敲黑板!!!我们现在是在shopoperation.html文件中引入common.js的,但是shopoperation.html的路径全称是什么,是WEB-INF/html/shopoperation.html,看图一项目架构,common.js文件在resource文件下,WEB-INF目录外,即WEB-INF外面一层,这里加../,就返回到了webapp目录下面,看下图

                                                                                                图八

所以现在common.js的访问是在webapp目录下进行的访问,访问地址为:resources/js/common/common.js,大家看这个路径是不是眼熟?其实我们对这个访问路径在图三做了配置(第一个红箭头),即专门为访问静态资源做了一个访问路径级别的拦截设置,这个设置是高于缺省拦截设置的,所以在进行resources/js/common/common.js访问的时候,被这里拦截下来了,不会通过图二的缺省拦截,因此可以直接访问到所需的静态资源。(如果对<mvc:resources mapping="/resources/**" location="/resources/" /> 这个代码意思不同的,可以百度一下

)结果如图六所示。

我这里再给道友们捋一下 src不加../的 整个shopoperation.html 的访问过程。

首先在浏览器地址栏中输入http://localhost:8080/o2o/shopadmin/shopoperation  ,因为图二配置了缺省拦截也就是等级最低的拦截,也就是可以拦截所有的请求,那么这个访问地址就会被拦截,通过图四配置,找到shopoperation.html。翻译一下:shopoperation.html真实的访问路径其实可以理解为:

 http://localhost:8080/o2o/shopadmin/WEB-INF/html/shopoperation.html (看图三前后缀配置,当然这这只能通过后台转发,访问WEB-INF文件),大伙儿注意shopoperation.html文件其实是在WEB-INF目录下的。

接着,在加载shopoperation.html后,如图五所示,由于在shopoperation.html中需要引用webapp目录下resources目录下的common.js文件,根据src中的地址 src='../resources/js/common/common.js',这里重新再次发出请求。重点来了,敲黑板!!!我们现在是在shopoperation.html文件中引入common.js的,但是shopoperation.html的路径全称是什么,是WEB-INF/html/shopoperation.html,看图一,common.js文件在resource文件下,WEB-INF目录外,即WEB-INF外面一层,这里没有加../没有返回它的上一级目录,就必然还在WEB-INF目录下引用common.js文件

                                                                                              图九

所以现在common.js的访问是在WEB-INF目录下的访问,访问的真实路径是WEB-INF目录下的resources/js/common/common.js,由于外界访问WEB-INF中的内容必须通过内部转发,由于没有专门为这个路径定义过拦截(我们在图三定义的是webapp目录下的路径拦截),只能由默认的缺省拦截(即图二设置)进行拦截,进入到图四controller层中,首先进入

@RequestMapping(value = "shopadmin", method = { RequestMethod.GET })

由于我们没有进一步定义类似

@RequestMapping(value = "/shopoperation")的映射

如@RequestMapping(value = "/resources")的映射

所以访问只能到shopdamin为止,最终的common.js访问地址为:http://localhost:8080/o2o/shopadmin/resources/js/common/common.js 即图七所示。

 

后记:

写到这,可以说,昨晚一个遗留的问题到此可以画上一个句号了。想了想,今天花了一整天研究这个,花时间有点长的,这从侧面说明自己要学的东西还有很多很多。当然也有朋友问我,花这么多精力和时间搞这个路径问题是不是代价有点大,我笑了笑说谁知道呢。不过有一点可以确认,我说服了我自己,今晚可以睡个好觉。不写了,回宿舍睡觉了。由于时间太晚,书写可能有点问题,另外文中的观点和内容仅代表个人观点,可能有错误之处,还请大家谅解,毕竟水平有限~~,谢谢大家观阅

 

 

 

 

 

 

;