假设应用程序的 contextPath 为 /ctx,在 http://localhost:8080/ctx/a/b 资源中,咱们转发和重定向到 http://localhost:8080/ctx/x/y 资源,分别应该怎么写?
转发,是在同一个应用程序中,请求从由资源 A 处理,到由资源 B 处理。资源 A 和资源 B 属于同一个应用程序的资源,它们老是相对于该应用程序的 contextPath 而言的。转发的资源可使用相对路径(不以 "/" 开头)和绝对路径(以 "/" 开头,这里的绝对,其实也是相对于某个环境而言的)。转发的资源若使用 "/" 开头,表明的是该资源在该应用程序中是绝对的,注意,是在应用程序的这个前提下是绝对的。
资源 A = http://localhost:8080/ctx/a/b,资源 B = http://localhost:8080/ctx/x/y。在资源 A 中 getRequestDispatcher("/x/y"),因为是以 "/" 开头,所以在应用程序内部是绝对的,即在 http://localhost:8080/ctx 这个环境下,/x/y 表明的是绝对地址。注意,我并无写 getRequestDispatcher(request.getContextPath() + "/x/y"),这样写的话,一样是在 http://localhost:8080/ctx 这个环境下的绝对地址为 request.getContextPath() + "/x/y",那么完整的资源是 http://localhost:8080/ctx/ctx/x/y,并非咱们所指望的资源。
在资源 A 中 getRequestDispatcher("x/y") 会如何呢?因为转发的资源不是以 "/" 开头,所以它是一个相对地址,相对于谁呢?相对于作转发操做的资源的地址,即相对于 http://localhost:8080/ctx/a/b,其路径为 http://localhost:8080/ctx/a,所以,转发后的资源的地址为 http://localhost:8080/ctx/a/x/y!若是由资源 /ctx/a/b 转发到 /ctx/a/c,因为这两个资源所处的路径相同,咱们固然能够这样写:getRequestDispatcher("c")
综上所述,不建议使用相对路径来转发资源。尽可能使用绝对地址来转发资源,同时,不要在资源的前面又多此一举的加上 request.getContextPath(),由于转发操做原本就是在同一个应用程序之间来处理的!
重定向,不只能够重定向到当前应用程序(http://localhost:8080/ctx)中的其它资源,还能够重定向到同一个站点上的其它应用程序(http://localhost:8080/another)中的资源,甚至是使用绝对 URL 重定向到其它站点的资源。
被重定向的资源如果以 "/" 开头,如 /x/y,其实是相对于主机而言的,即完整的资源路径为 http://localhost:8080/x/y,这并非咱们想要的资源。
被重定向的资源若不是以 "/" 开头,如 x/y,其实是相对于作重定向操做的资源(http://localhost:8080/ctx/a/b)而言的,即完整的资源路径为 http://localhost:8080/ctx/a/x/y,这也不是咱们想要的资源。固然,使用这种方式,咱们重定向到 /ctx/a/c,即 sendRedict("c") 固然是没问题的。
使用绝对 URL 还能够将资源重定向到其它站点的资源。
综上所述,作重定向操做时,若想重定向同一个应用程序的其它资源时,一样不推荐使用相对路径,尽可能使用绝对路径,同时,务必在资源前面加上 request.getContextPath()。
一句话总结:建立 RequestDispatcher 对象时指定的 URL 以“/”开头,它是相对于当前 WEB 应用程序的根目录;HttpServletResponse.sendRedirect 方法的 URL 以“/”开头,它是相对于整个 WEB 站点的根目录。spa