1.URI,URL,URN
在很多地方看到uri和url的区别,但是都没有说清楚,有的说uri是url去掉协议和query string的那一部分,这种说法是不对的,下面是URI Standard (RFC3986) 在 1.1.3 小节“URI, URL, and URN”中对三个概念的澄清:
URI 可以进一步分为定位器、名称,或者二者兼具。术语“Uniform Resource Locator” (URL) 涉及的是 URI 的子集,除识别资源外,它还通过描述其最初访问机制(比如它的网络“位置”)来提供定位资源的方法。 术语“Uniform Resource Name” (URN) 在历史上曾用于引用“urn”方案 [RFC2141] 下的 URI,这个 URI 需要是全球惟一的,并且在资源不存在或不再可用时依然保持不变,对于其他任何拥有名称的一些属性的 URI,都需要使用这样的 URI。
也就是URL和URN是URI的子集。
URI的语法由其scheme决定,“一般URI”包括四个组件,如下:
<scheme>://<authority><path>?<query>,除了<sheme>,其他的组件有可能不存在。
1). scheme = alpha *( alpha | digit | "+" | "-" | "." )
2). authority = server | reg_name
3). path = [ abs_path | opaque_part ]
4). query = *uric (字符串信息)
absoluteURI = scheme ":" ( hier_part | opaque_part )
hier_part是指需要有分隔符对不同等级的组件进行分割,opaque_part指不需要有分隔符对不同组件进行分割。
hier_part = ( net_path | abs_path ) [ "?" query ]
net_path = "//" authority [ abs_path ]
abs_path = "/" path_segments
opaque_part = uric_no_slash *uric
uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "
relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
这里还有一个术语URI-reference,看了下面的等式就明白了:
RI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] (例:http://www.apps.ietf.org/rfc/rfc2396.html#sec-3.1)
因为URL和URN的子集,所以它们也遵循上面的语法。
2.Servlet中的requestURI,requestURL,ServletPath,ContextPath,PathInfo相关概念
1)contextPath: 和此servlet所在的ServletContext关联的路径前缀,如果该context是root,这contextPath的值是空串;若不是root,返回的值是以"/"开头的。在tomcat中,就是在sever.xml中,就是对应当前servlet的context的节点中的path属性<context docBase="mywebwork" path="/mywebwork" .../>
2)ServletPath: 与mapping相对应的path部分,以"/"开始,但如果该映射是"/*",那么servlet路径此时为""
3)PathInfo: servlet的附加路径,即访问路径中servlet名称之后,QueryString之前的那一部分,如果没有则为null,如果有以"/"开始
下面是servelet specification中的例子:
Table 1: Example Context Set Up
Context Path /catalog
Servlet Mapping Pattern: /lawn/*
Servlet: LawnServlet
Servlet Mapping Pattern: /garden/*
Servlet: GardenServlet
Servlet Mapping Pattern: *.jsp
Servlet: JSPServlet
Table 2: Observed Path Element Behavior
Request Path Path Elements
/catalog/lawn/index.html ContextPath: /catalog
ServletPath: /lawn
PathInfo: /index.html
/catalog/garden/implements/ ContextPath: /catalog
ServletPath: /garden
PathInfo: /implements/
/catalog/help/feedback.jsp ContextPath: /catalog
ServletPath: /help/feedback.jsp
PathInfo: null
4)requestURI和reqeustURL: URI和路径之间除了URL编码区别外,等式requestURI = contextPath + servletPath + pathInfo是成立的,不要把这里的requestURI及requestURL和上文中所述的URI和URL混淆,这里指的是在servlet中适用的约定,譬如这里的requestURI不包括查询字符串参数,而实际IETF文档中URL是可以有查询参数的。HttpServletRequest提供如下API去获取requestURI和requestURL:
getRequestURI() :返回请求URL中从主机名到查询字符串之间的部分(servlet specification的说法是返回HTTP请求的第一行请求URL中从协议名称到查询字串的那部分)。例如:
First line of HTTP request Returned Value
POST /some/path.html HTTP/1.1 /some/path.html
GET http://foo.bar/a.html HTTP/1.0 /a.html
HEAD /xyz?a=b HTTP/1.1 /xyz
getRequestURL():重新构造客户端用于发起请求的URL。返回的URL包括了协议、服务器的名字、端口号和服务器的路径,但是不包括查询字符串参数。