原创不易,转载请联系作者。
昨晚临回宿舍之前遇到一个访问静态资源路径的问题,研究了一会儿,没有研究出来。今天一早打开电脑,屏幕是昨天遗留的问题,越看越想解决它,要不然心里很不舒服。没想到这一深入研究,挖掘出以前许多和这相关但没注意的知识,结果陷入进去了,本来是一个问题,但逐渐转变成一小块知识的问题,就这样逐渐摸索和排盲,白天的时间很快过去了,虽然感觉自己离最终的答案很近了,可还是没有一个很清晰的严密回答。晚饭回来,继续研究,直至写这篇博文之前,终于搞懂了来龙去脉,特此记录一下,希望能帮助遇到类似问题的道友,能尽快地解决问题,在有限的时间内去学习更多的知识。
道友们别急,首先我把整个项目的文件架构列出来,具体问题要根据图中的内容才能指出。
项目目录:
图一
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 即图七所示。
后记:
写到这,可以说,昨晚一个遗留的问题到此可以画上一个句号了。想了想,今天花了一整天研究这个,花时间有点长的,这从侧面说明自己要学的东西还有很多很多。当然也有朋友问我,花这么多精力和时间搞这个路径问题是不是代价有点大,我笑了笑说谁知道呢。不过有一点可以确认,我说服了我自己,今晚可以睡个好觉。不写了,回宿舍睡觉了。由于时间太晚,书写可能有点问题,另外文中的观点和内容仅代表个人观点,可能有错误之处,还请大家谅解,毕竟水平有限~~,谢谢大家观阅