1. 请求URI简介:
1) 请求URI就是URL中域名之后和请求参数之前的部分,比如:http://localhost:8080/ServletSets/test1.view?name=Tom&id=89中,请求URI就是/ServletSets/test1.view;
2) 请求URI决定了Web容器调用哪个具体的Servlet来响应请求,具体做法是Web容器用各个Servlet的URL模式来匹配请求URI中的内容,选择一个最合适的Servlet进行响应;
3) 请求URI的组成:requestURI = contextPath + servletPath + pathInfo
i. contextPath:即环境路径,即Servlet所在的应用程序环境根目录,比如servlet1放在目录ServletSets下,则contextPath就是/ServletSets;
ii. servletPath:即Servlet路径,即Servlet的URL模式指定的路径,比如@WebServlet("/test1/*"),则如果选中该Servlet则servletPath就是/test1;
iii. pathInfo:路径信息,即请求URI中除了环境路径和Servlet路径之外的路径,一般是URL模式后跟着的额外信息,比如上例中如果输入的URI是/test1/abc.view,则pathInfo就是/abc.view;
!!可以用HttpServletRequest的getRequestURI、getContextPath、getServletPath、getPathInfo来分别获取,三个分解后(即使用者四个函数获取后)得到的各个部分要没为null(空)要么必须以/打头!!
2. 不同URL模式对应的请求URI:
1) 这里用一个程序来测试不同URL模式对应的请求URI都是怎么样的,这里只展示doGet方法的模板:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
// response.getWriter().append("Served at:
// ").append(request.getContextPath());
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet Pattern</title>");
out.println("</head>");
out.println("<body>");
out.println("URI = " + request.getRequestURI() + "<br>");
out.println("Context Path = " + request.getContextPath() + "<br>");
out.println("Servlet Path = " + request.getServletPath() + "<br>");
out.println("Path Info = " + request.getPathInfo() + "<br>");
out.println("</body>");
out.println("</html>");
out.close();
}
!唯一要改变的地方就是@WebServlet的参数,用不同的URL模式来测试!
!!测试的URL为:http://localhost:8080/ServletSets...
!!因此contextPath始终都是/ServletSets
!!...就是不同的输入
!!接下来的测试都是围绕着...的不同来展开的
!!测试格式:[... :servletPath,pathInfo
2) 路径映射:
i. 模式:以/开头以/*结尾,两者中间不能为空,例如“/test/*”,所有以/test/开头或者是/test的...都会调用该Servlet;
ii. 测试:模式为"/test/*"
/test : /test,null
/test/ :/test,/
/test/abc.view : /test,/abc.view
3) 扩展映射:
i. 模式:以*.开头,但是*.之后不能为空,例如"*.view",所有以.view结尾的...都会调用该Servlet;
ii. 测试:模式为"*.view"
/xxx.view : /xxx.view,null // 由于通配符是在前面,所以pathInfo一定是null
4) 环境根目录映射:
i. 模式:空字符串“”,即只有当...为空或者/时才能请求到该Servlet,就好像改Servlet是环境根(目录)一样;
ii. 测试:模式为""
空 : "",/
/ : "",/
!!注意servletPath是""空字符串而不是null,再次验证了servletPath是跟随URL Pattern的,因为环境根目录映射的模式就是"",所以servletPath一定是"";
!!注意pathInfo是有的,即一个/,这个非常特殊,需要记忆!
5) 完全匹配:
i. 模式:不含通配符*,也不是环境根目录映射的其余映射,不能只含有一个/,因此必须以/打头,例如"/test.view",则必须...完全和/test.view一样才能调用该Servlet;
ii. 测试:模式为"test.view"
/test.view : /test.view,null // 由于为尾部无通配符,因此pathInfo必定为null
6) 默认映射/预设Servlet:
i. 模式:仅包含一个/,如果以上所有的方式都无法匹配上就调用该Servlet,但是...必须以/开头;
ii. 测试:模式为"/"
/abcdefg.xxx : /abcdefg.xxx,null // servlet为整个...,但是pathInfo为null,比较特殊,需要记忆
7) 匹配冲突:即当一个URL可以匹配上多个模式的时候Web容器该如何选择?Web容器会使用贪心法选择,和正则表达式的贪心匹配本质相同,即最大匹配原则,会先匹配完全匹配模式,如果能匹配上就调用那个模式的Servlet,如果没有一个能匹配上就再和有通配符的模式进行匹配,然后选除了统配符以外能匹配上最多字符的那个模式所代表Servlet进行响应;