在web应用服务中,常常会面对不一样SERVLET之间的跳转,目前咱们能够经过如下两种方式实现: html
1.RequestDispatcher.forward() java
2.ServletResponse.sendReDirect() web
二者的区别: 缓存
1.redirect 方式能够跨应用访问,forward 只能在同一个应用中跳转。 服务器
2.forward 客户端访问服务器,服务器找到要跳转的相应URL并执行返回给客户端。客户端的地址栏显示的是原始URL。 jsp
redirect 客户端访问服务器,服务器找到要跳转的URL并将URL发给客户端,再由客户端对新的URL从新发送请求。客 this
户端的地址栏显示的是第二次请求的URL。 url
3.数据的传输:在request中的数据,forward能够访问,redirect不行,由于redirect已是一个新的请求。 spa
forward跳转的理解: 线程
1.得到跳转
getRequestDispatcher方法以String参数描述ServletContext做用域的路径。该路径必须相对于ServletContext的根,而且以“/”开头。该方法使用路径(path)来查找servlet,用RequestDispatcher对象包装,而后返回结果对象。若是没有基于指定路径的servlet,提供一个RequestDispatcher返回路径值。
getNamedDispatcher方法以String参数表示ServletContext已知的servlet名称。若是找到servlet,用RequestDispatcher对象将它包装并返回。若是没有和指定名称关联的servlet,该方法必须返回null。
为了可以使用当前请求的相对路径(不是ServletContext根的相对路径)来得到RequestDispatcher对象,ServletRequest接口提供如下方法:
getRequestDispatcher
该方法的行为和ServletContext的同名方法相似。servlet容器使用request对象中的信息将指定的相对路径转换成完整路径。好比,以“/”为根的上下文,请求/garden/tools.html,经过ServletRequest.getRequestDispatcher("header.html") 得到的requestDispatcher实际上等同于调用ServletContext.getRequestDispatcher("/garden/header.html")。
1.1 RequestDispatcher路径的query字符串
ServletContext和ServletRequest使用path参数建立RequestDispatcher对象的方法,容许在path后添加query字符串。好比,开发人员能够经过下列代码得到RequestDispatcher:
String path = “/raisons.jsp?orderno=5”;
RequestDispatcher rd = context.getRequestDispatcher(path);
rd.include(request, response);
query字符串中指定的参数用来建立RequestDispatcher,优先于传递给包含servlet的同名的其余参数。该参数和RequestDispatcher关联,只在include或forward调用中有效。
2 使用RequestDispatcher
要使用requestDispatcher,servlet能够调用RequestDispatcher接口的include或forward方法。这些方法的参数能够是经过Servlet接口的service方法传递的request和response参数,也能够是规范2.3中引入的request和response包装类的子类的实例。后者,包装实例必须包装容器传递给service方法的request和response对象。
容器供应商必须确保向目标servlet转发请求和原请求处于同一个VM,同一个线程。
3 include方法
RequestDispatcher接口的include能够随时调用。include方法的目标servlet能够完整访问request对象,可是使用response对象上有一些限制:
它只能向response对象的ServletOutputStream或者Writer写入信息,提交响应(将内容输出到响应缓冲尾部),或者显式调用ServletResponse接口的flushBuffer方法。它不能设置header,或者调用任何影响响应header的方法。任何那样的尝试必须都被忽略。
3.1 包含的请求参数
除了使用getNamedDispatcher方法得到的servlet以外,include的servlet能够访问调用它的路径。设置如下请求属性:
javax.servlet.include.request_uri
javax.servlet.include.context_path
javax.servlet.include.servlet_path
javax.servlet.include.path_info
javax.servlet.include.query_string
include的servlet的这些属性经过request对象的getAttribute方法访问。
若是include的servlet经过getNamedDispatcher方法得到,那么这些属性没有设置。
4 forward方法
RequestDispatcher接口的forward方法只有在输出还未提交给客户端时,才能够由调用servlet调用。若是输出数据存在于还未提交的响应缓冲中,内容必须在目标servlet的service方法调用以前清空 (不然out.println()输出的都在缓存中,无效)。若是响应已被提交,必须抛出IllegalStateException异常。暴露给目标servlet的request对象的path元素必须映射用来得到RequestDispatcher的路径。
惟一例外是若是RequestDispatcher是经过getNamedDispatcher方法得到的,这种状况下,request对象的path元素必须必须映射最初的请求。
在RequestDispatcher接口的forward方法返回以前,servlet容器必须发送,提交并关闭响应内容。
4.1 query字符串
请求转发机制负责在转发(forward)或包含(include)请求时传递query字符串。
5 错误处理
若是requesDispatcher的目标的servlet抛出ServletException或IOException类型运行时异常或checked异常,应当将它传递给调用servlet。全部其它异常应当包装成ServletException异常,而且异常的根在传递以前设置为原始异常。
相对路径的理解:
forward中"/"相对于web应用.
从http://localhost:8080/Test/gw/page.jsp中转发
<jsp:forward page="OtherPage.jsp"/>在JSP页面被解析后转换成pageContext.forward("OtherPage.jsp");
"/OtherPage.jsp"提交到http://localhost:8080/Test/OtherPage.jsp
"OtherPage.jsp"提交到http://localhost:8080/Test/gw/OtherPage.jsp
<form action="/ddd"> 和 response.sendRedirect("/ddd"); 相对于服务器根路径.
假设转发代码包含于注册的servlet-url为/ggg/tt;jsp为/ggg/tt.jsp:
绝对路径:response.sendRedirect("http://www.brainysoftware.com")发送http://www.brainysoftware.com
根路径:response.sendRedirect("/ooo")发送至http://localhost:8080/ooo
相对路径:response.sendRedirect("ooo")发送至http://localhost:8080/Test/ggg/ooo,