关于JavaWeb开发的Servlet中,有这样几个函数很绕人:
String RequestURI=req.getRequestURI();
String ServletPath =req.getServletPath();
String ContextPath=req.getContextPath();
String PathInfo=req.getPathInfo();
它们有着怎样的对应关系呢?
RequestURI = ContextPath + ServletPath + PathInfo;
假如有一个WEB项目部署在Tomcat中,项目名称为TestWeb,我们配置了如下的Servlet:
<servlet-mapping>
<servlet-name>BgMainServlet</servlet-name>
<url-pattern>/back/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ActionHandleServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/back/list.action</url-pattern>
</servlet-mapping>
在了解路径之前,我们先要了解Servlet的匹配规则,一共有三种:
1、精确匹配,例如
<servlet-mapping>
<servlet-name>CustomerServlet</servlet-name>
<url-pattern>/back/list.action</url-pattern>
</servlet-mapping>
2、路径匹配,例如
<servlet-mapping>
<servlet-name>BgMainServlet</servlet-name>
<url-pattern>/back/*</url-pattern>
</servlet-mapping>
3、后缀名匹配,例如
<servlet-mapping>
<servlet-name>ActionHandleServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
其匹配优先级为:精确匹配》路径匹配》后缀名匹配
即如果访问链接是http://localhost:8983/TestWeb/back/aa/bb/?s=123
匹配的是BgMainServlet。
如果访问链接是http://localhost:8983/TestWeb/back/list.action
尽管/back/*和/back/list.action都符合规则,根据 精确匹配》路径匹配,匹配到CustomerServlet。
如果访问链接是http://localhost:8983/TestWeb/back/others.action
尽管*.actiont和/back/*都符合规则,根据 路径匹配》后缀名匹配 ,匹配到BgMainServlet。
在一个访问链接中,一个URL一共有如下几个部分:
URL=协议类型+主机名+端口号+文件+参数
每个部分之间都有间隔符号将他们区分
连接部分 |
间隔符号 |
协议类型 - 主机名 |
:// |
主机名 - 端口号 |
: |
端口号 - 文件 |
/ |
路径 - 参数 |
? |
比如http://localhost:8983/TestWeb/back/aa/bb/?s=123
协议类型 |
http |
主机名 |
localhost |
端口号 |
8983 |
文件 |
/TestWeb/back/aa/bb/ |
参数 |
s=123 |
以http://localhost:8983/TestWeb/back/aa/bb/list.do为例
在Sertlet中函数及对应关系为
Request类中的函数 |
返回结果 |
案例URL的值 |
getRequestURI() |
URL的文件部分 |
/TestWeb/back/aa/bb/ |
getContextPath(); |
项目名称 |
/TestWeb |
getServletPath(); |
匹配的servlet |
/back |
getPathInfo(); |
URL中Servlet后的实际请求路径 |
/aa/bb/list.do |
最终得出结论:RequestURI= ContextPath+ ServletPath + PathInfo;
弄清楚了上面的关系,还有几点是需要注意的。
1、所有Servlet的url-pattern都是从ContextPath后面开始匹配的。
2、每一次请求,只会匹配一个Servlet。
到这里就有一些好玩儿的东西了。我们如何用Servlet来实现Filter的功能呢?
答案:
用Request.getRequestDispatcher(url).forward(request, response);
进行请求的转发。
这里的url可以使用相对路径。
如果在BgMainServlet中doGet方法如下:
protectedvoid doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
request.getRequestDispatcher("/back/aa/")
.forward(request, response);
//或者用
//request.getSession().getServletContext()
//.getRequestDispatcher("/TestWeb/back/aa/")
//.forward(request, response);
}
那么我们将请求转到的实际url为
http://localhost:8983/TestWeb/back/aa/
这个url会继续匹配Servlet,而且匹配到的Servlet是BgMainServlet
这样的话,就变成了一个死循环。
我们只要结合web.xml改变重定向的url就可以在Servlet中实现类似于Filter的功能,是不是很酷?
参考文章:
getRequestDispatcher()与sendRedirect()的区别
request.getPathInfo() 方法的作用
电脑URL的组成