一 介绍
在web.xml中通过<servlet/>
元素可配置servlet,<servlet-mapping/>
元素可以配置servlet对应的地址,如下面所示:
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlet拦截配置 -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
下面讲的是<url-pattern/>
元素的使用,url-pattern
指的是url中位于http://host:port + WebAppName
之后部分的匹配模式,比如<url-pattern>/foo</url-pattern>
时,此时servlet匹配的url为http://DomainName/WebappName/foo
二 url-pattern设置
一共五种设置方式:
<url-pattern>/*</url-pattern>
:/*
将该web应用的所有的url映射到该servlet上<url-pattern>/</url-pattern>
:/
表示该servlet为默认servlet,只有其他映射匹配不成功时,则传给该servlet处理,比如tomcat就有一个default的默认servlet。<url-pattern></url-pattern>
:元素内容为空,表明当url请求web应用的根目录时,由该servlet处理,也就是将根目录映射到该servlet上。- 前端的控制器的映射:比如上面的dispatcher Servelt就是一个前端控制器,除了上面使用第二种方法外,还可以将该servlet映射到部分url上,比如
*.html
,*.do
,/pages/*
,/app/*
等等。 - 不使用通配符:比如
/foo/
(目录)、/foo.html
(文件)、/foo/foo.jsp
等等,则servlet被映射到一个具体的url上
注意
- 在xml中,之后配置的url会覆盖前面配置的url
- url必定含有路径,即使url中路径为空,比如url为
http://example.com
时,即使没有路径,也会默认指向/
根路径;也可显式给出根路径:http://example.com/
。当路径以/
结束时,表示url指向目录,否则指向文件。目录也可以不以/
结尾。- 不要将url匹配模式和url混淆。
三 url解析流程
- 当有请求时,会先检测该url是否有对应映射的servlet,如果有,则执行该servlet;否则,匹配不成功,转2
- 如果url指向一个文件,则将该文件交给默认servlet处理;否则url指向目录,转3
- 查看该目录下是否有welcom-file-list列表指定的文件,如果有,则url重新指向该文件,转1;否则,执行默认servlet,但返回404。
注意
- index.jsp不应该被默认servlet处理,而是应该由jsp引擎解析;而jsp引擎是一个servlet,负责解析jsp文件。
- 只有其他servlet映射不成功时,才会执行默认servlet。默认servlet处理的一般是静态文件,如html、css、js等等。
- 第2、3步应该都是默认servlet处理的。
四 其他
4.1 welcome-file-list
welcome-file-list列表指定的是该目录下的默认欢迎文件,即url即使访问的是目录,也会尝试返回列表中指定的一个文件。通过将servlet映射到指向目录的url上也能达到同等目的,但是welcome-file-list更为方便。
举个例子:映射一个servlet到http://example.com/webapp/user/
这个目录上,即<url-pattern>/user/</url-pattern>
,此时也配置了welcom-file-list,按照url解析流程,该servlet匹配该url,执行该servlet,结束。
4.2 springMVC后端控制器映射
被前端控制器(DispatcherServlet)拦截的url会根据HandlerMapping配置分发到成功匹配的后端控制器,由该控制器处理请求。因此只有前端控制器拦截到了url,才可能会传给后端控制器。
例子1
前端控制器被映射到/
,此时DispatcherServlet为默认servlet。声明一个后端控制器如下:
@RequestMapping("/user2/")
public String testUser() {
...
}
并且/user2/
目录下存在index.jsp。当url为http://example.com/webapp/user2/
时,会发生什么?
会执行index.jsp文件。根据url解析流程,通过welcome file list找到index.jsp文件,匹配第三条规则;转1,匹配jsp引擎,执行该引擎(jsp引擎是一个servlet)。
例子2
当DispatcherServlet映射到/*
,然后访问http://example.com/webapp/
,此时会被DispatcherServlet拦截,不是welcome-file-list指定的文件,因为/*
匹配所有url,满足规则一。
但如果启用了spring mvc的DefaultServletHttpRequestHandler,那么DispatcherServlet会将没有被后端控制器匹配的URL交给servlet容器的默认servlet。下面默认启用这项配置。
- 如果上述url没有被匹配,会被交给默认servlet处理,直接404!因为没有了查找welcom file列表的过程了。
- 如果url访问
http://example.com/webapp/index.html
,没有被后端控制器匹配,交给默认servlet处理,那么会返回该网页。 - 如果URL为
http://example.com/webapp/index.jsp
,同样也交给了默认servlet处理。此时会如何?会被打印jsp中的源码!!这是因为jsp文件没有被jsp引擎执行,而是被默认servlet执行的。
4.3 tomcat的默认配置
tomcat在全局web.xml文件(在conf目录下)中为所有web应用配置了一个默认servlet和jsp引擎。全局web.xml相当于添加在每个web应用的web.xml之前,因此可以修改各自应用的web.xml文件来覆盖默认的设置。下面给出conf下web.xml的部分内容:
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- The mappings for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>
可以看出,默认servlet的url匹配模式为/
,jsp引擎为*.jsp
或*.jspx
其实全局web.xml中也配置了welcome-file-list列表,因此不用我们自己配置。如:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
默认servlet用来处理静态文件,而静态文件有很多种类型,返回响应时会在content-type
头字段中指定它的MIME类型。
默认servlet如何得知静态文件的MIME类型呢?可以通过文件后缀名得到它的MIME类型。因此在全局web.xml中配置了大量后缀名到MIME类型的映射。内容太多,请自行查看。
参考
url-pattern:https://stackoverflow.com/questions/4140448/difference-between-and-in-servlet-mapping-url-pattern
servlet-mapping的文档介绍:https://docs.oracle.com/cd/E24329_01/web.1211/e21049/web_xml.htm#WBAPP531
welcome file的介绍:https://docs.oracle.com/cd/E24329_01/web.1211/e21049/configurejsp.htm#WBAPP185
参考了最后一行:https://blog.youkuaiyun.com/qq_15237993/article/details/72868089