【二月】spring-mvc学习之静态资源访问(servlet匹配规则学习)

自满是成功的杀手,唯有持续的奋斗才是成长的源泉
--苏格拉底

最近在学习spring-mvc,在成功搭建spring-mvc的环境后,使用html写了一个简单的登陆页面,但是在启动服务后,访问相应的页面,报404,找不到对应的资源。百思不得其解,于是乎跟了一下源码,尝试一下自己解决。

我使用的版本为:

  • tomcat : 8.5.9
  • spring-webmvc : 4.2.3.RELEASE
  • jstl : 1.2

web.xml中DispatcherServlet的配置如下:

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring-mvc-config.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

跟源码后发现,在请求对应的html页面的时候,请求被DispatcherServlet处理了,在由其doDispatch处理的时候,无法获取到对应的handler。于是乎自作聪明,想着对对应的html页面写一个Controller不就好了吗?最后发现是不行的,暂时发现对应Controller的页面需要是jsp(这个可能是自己试用jstl解析视图的原因,具体细节还要学)。

可是之前自己在学习servlet的时候,是可以访问静态的html页面的。为什么在使用spring-mvc的框架后会提示无法访问呢?问题就出在DispatcherServlet的路径映射上了。

servlet的路径匹配规则

当键入一个url后,servlet容器是如何进行路径的匹配的呢?具体的匹配规则是什么呢?匹配的顺序是怎样的?

首先,serlvet容器会用请求的url减去当前应用的上下文路径,然后以剩余的字符串进行匹配,假设现在我们请求的url为http://localhost:8080/servlet/index/index.html,他的应用上下文为servlet,容器就会将http://localhost:8080/servlet去掉,使用/index/index.html进行匹配,以选择对应处理请求的serlvet。

servlet 的匹配规则有四种,按匹配顺序排列。

  1. 精确匹配。精确匹配的就是请求的路径与servlet定义的url-pattern完全匹配。

  2. 路径匹配。假如一个资源路径下的所有资源页面对应的请求都需要有一个serlvet进行处理,这可以使用路径匹配规则。路径匹配规则以/开口,并以/*结尾

<!-- 对应的servlet会处理以 /index/ 开头的请求 -->
<servlet-mapping>
    <servlet-name>servlet</servlet-name>
    <url-pattern>/index/*</url-pattern>
</servlet-mapping>
  1. 扩展名匹配。匹配指定扩展名字的文件,路径匹配规则以*.开头
<!-- 对应的servlet会处理对html文件的请求 -->
<servlet-mapping>
    <servlet-name>servlet</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>
  1. 默认匹配。默认路径匹配规则的路径就一种:/

⚠️注意:在一个请求经由servlet容器处理的时候,servlet容器按照顺序进行匹配,当匹配中的时候,就将请求交给对应的servlet进行处理,单一匹配。

问题再次分析

很显然,我将DispatcherServlet的匹配路径定义为了默认匹配,然后没有定义其他的servlet,导致所有的请求都有DispatcherServlet进行处理了。所有,如果定义一个可以处理静态资源的serlvet就可以了,由此出发,回想最初使用servlet的时候,为什么可以处理静态资源的访问呢?抱着疑问上网搜索了一下,发现原来在tomcat的conf目录下由一个web.xml文件,打开这个web.xml文件,其中定义了DefaultServlet。我们看一下这个文件:

DefaultServlet.png

其对应定义的匹配路径为:

DefaultServlet路径映射规则

在我后续将DispatcherServlet的路径映射定义为默认后,我定义的覆盖了tomcat的默认的servlet,这就是问题原因了。找到问题原因了,怎么解决呢?

解决办法

解决办法一:

为tomcat的DefaultServlet定义一个优先级更高的匹配。扩展名匹配或者是路径匹配。

<!-- 让DefaultServlet来处理html,js,css文件 -->
<servlet-mapping>
 <servlet-name>default</servlet-name>
 <url-pattern>*.html</url-pattern>
 <url-pattern>*.css</url-pattern>
 <url-pattern>*.js</url-pattern>
</servlet-mapping>

<!-- 假设所有的资源都放在resource这个目录下 -->
<servlet-mapping>
 <servlet-name>default</servlet-name>
 <url-pattern>/resource/*</url-pattern>
</servlet-mapping>

解决办法二:

让spring-webmvc来为我们解决静态资源访问的问题。spring中定义了一个DefaultServletHttpRequestHandler来处理静态资源。我们可以看一下官方对它的介绍:

DefaultServletHttpRequestHandler.png

大概的意思就是,这个DefaultServletHttpRequestHandler是spring提供用来处理静态资源的。可以在spring的配置文件中对它进行配置就好了。

<mvc:default-servlet-handler/>

<!-- 两种选其中一种就好了 -->

<bean class="org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler"></bean>

自此,静态资源的访问解决了,但是这其实解决了配置问题,其中具体的细节自己还是不了解,还是要深入进行学习。学无止境啊!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容