requestURI
当在浏览器地址栏中键入一个URL,比如:
http://www.abcd.com/helloweb/hello/pathinfo1/pathinfo2
网络协议会将域名解析为ip地址,并将请求转发到HTTP服务器,这部分不是web容器的工作。web容器只需要解析剩下来的路径部分:
/helloweb/hello/pathinfo1/pathinfo2
这部分路径就是requestURI,可以通过HttpServletRequest : getRequestURI获得这个路径的字符串。
解析路径
接下来就是解析requestURI,requestURI被分为三个部分:
- requestURI=contextPath+servletPath+[pathInfo]
下面逐条分析。
contextPath
首先,以’/'分隔的第一部分被定义为contextPath,以上面的请求为例,contextPath对应的是:
/helloweb
web容器要根据contextPath找到对应的web应用,主要有三种对映方式:
- webapps目录下的应用根目录名。
- conf目录下的servel.xml文件中的Context标签的path属性设置。
- conf/catalina/localhost目录下对应的xml文件的文件名。
web容器会根据其中一种方法找到对应的应用。
配置映射
现在URI只剩下这部分了:
/hello/pathinfo1/pathinfo2
这部分将会参与到servletPath和pathInfo的解析。
web容器根据servletPath找到对应的Servlet。不过对应关系可不是Servlet的名字这么简单,而是通过配置的映射来决定。
可以有两种方式配置映射:
- @WebServlet注解中的urlPatterns属性
- web.xml中的url-patterns标签
映射主要有如下几种模式:
- 完全匹配映射,比如@WebServlet(urlPatterns = “/hello/pathinfo1/pathinfo2”),url模式与url剩下来的路径完全一模一样,只要少一个字符都或报错。
- 默认映射,比如@WebServlet(urlPatterns = “/”),当找不到Servlet时,会使用默认的Servlet。
- 扩展映射,比如@WebServlet(urlPatterns="*.html"),只有带html后缀的请求才会映射到该Servlet。
- 路径映射,比如@WebServlet(urlPatterns="/hello/*"),会匹配以/hello/开头的所有url。
如果有多条映射都匹配的话,则选择最严格的匹配。
servletPath和pathInfo
上面提到配置映射的四种方式,只有路径映射才能用HttpServletRequest:getPathInfo()取得一个不为空的字符串,字符串是与url模式中通配符*匹配的部分。
其他的模式匹配的Servlet中剩下的路径信息都属于contextPath,pathInfo为null。
测试
说了半天我自己都糊涂了,下面看以下测试的结果把
URL | url模式 | contextPath | patnInfo |
---|---|---|---|
/hello/pathinfo1/pathinfo2 | / | /hello/pathinfo1/pathinfo2 | null |
/hello/pathinfo1/pathinfo2 | /* | 空字符串 | /hello/pathinfo1/pathinfo2 |
/hello/pathinfo1/pathinfo2 | /hello/* | /hello | /pathinfo1/pathinfo2 |
/hello/pathinfo1/pathinfo2 | /hello/pathinfo1/pathinfo2 | /hello/pathinfo1/pathinfo2 | null |
/hello/pathinfo1/pathinfo2.html | *.html | /hello/pathinfo1/pathinfo2.html | null |