JAVA学习——forward和sendRedirect区别总结

request.setAttribute()怎么用的?
JSP1代码
String [] test=new String[2];
test[0]="1";
test[1]="2";
request.setAttribute("test",test) ;
response.sendRedirect("jsp2.jsp");
 
JSP2代码
String test[]=(String[])request.getAttribute("test");
out.print(test);
 
但在JSP2中会找不到test。
 
     Why?
     首先解释一下reques周期:setAttribute用来在同一个request周期中保存变量使用。比如servlet调用后,并调出JSP页面,这是一个request周期,如果要在JSP页面需要servelet中的一些处理结构,就从request.getAttribute中获取。
 
     而对于上面的sendRedirect()方法是通过浏览器重定向的,所以第二个JSP页面中获得的request并非是前一个页面的request(两次请求生成了前后两个不同的request对象)
 
request.getAttribute()与request.setAttribute()
     request.getAttribute("nameOfObj")可得到JSP页面表单中控件的value。表单控件中的object的name和value是存放在一个哈希表中的,所以可以根据object的name找到对应的value
     而不同页面传值使用request.setAttribute("nameOfObj","valueOfObj")时,只会从jsp1到jsp2一次传递,之后这个request就会失去它的作用范围,再传就要再设置一个request.setAttribute()。而使用session.setAttribute()会在一个过程中始终保有这个值,但是session的使用要符合其他规范,具体要求再google。
 
用RequestDispatcher接口的forward()方法试试看
 
List list = new CommonsDao().getAllCommons();
request.setAttribute("CommonsList", list);
request.getRequestDispatcher("View.jsp").forward(request, response);
 
 
request.getRequestDispatcher()和response.sendRedirect()区别
     request.getRequestDispatcher()是请求转发,前后页面共享一个request
     response.sendRedirect()是重新定向的,前后页面不是一个requst
 
     sendRedirect通知浏览器再次提交一个http请求
     dispatcher是直接转到目的地址,最直接的表现是dispatcher后的url地址是改变的
 
     request.getRequestDispatcher()是服务器端跳转
     response.sendRedirect()是客户端跳转
 
     我的理解是:
     sendRedirect()请求重定向,类似于超链接。比如在A页面写一个request.setAttribute,sendRedirect到B页面:
     服务器------response---->A页面 ------request---->B页面
     真实情况是:
     A页面 ------request---->服务器 (sendRedirect操作) ------response---->A页面(然后浏览器)------request------> 服务器------response-------> B页面
                                                                                  
     即包含了两次request和response,因此是不能再B页面取到request.setAttribute里的值,能从url看到改变
     
     request.getRequestDispatcher().forwar(request,reponse)是请求分发器,比如你在A页面中写一个reuqest.setAttribute, request.getRequestDispatcher().forwar(request,reponse)到B页面,那就是说服务器给你的response是B页面的,并且只有一次request和response,所以只能在B页面取到request.setAttribute里的值,url仍是A页面的。
 
 
总结:
     sendRedirect实现请求重定向,forward实现的是请求转发。
1.跳转方式
      运用forward方法只能重定向到同一个Web应用程序中的一个资源。而sendRedirect方法可以让你重定向到任何URL。
      表单form的action= "/uu ";sendRedirect( "/uu ");表示相对于服务器根路径。
      如http://localhost:8080/Test应用(则提交至http://localhost:8080/uu); forward代码中的 "/uu "则代表相对与WEB应用的路径。如http://localhost:8080/Test应用(则提交至http://localhost:8080/Test/uu);
2.参数传递方式
     forward重定向后,浏览器url地址不变,sendRedirect转发后,浏览器url地址变为目的url地址。
     forward重定向将原始的HTTP请求对象(request)从一个servlet实例传递到另一个实例,而采用sendRedirect方式两者不是同一个application。
     forward的form参数跟着传递,可以使用setAttribute来传递参数到下一个页面。sendRedirect只能通过链接传递参数,response.sendRedirect(“login.jsp?param1=a”)。
3.服务器端和浏览器端
     使用forward重定向的过程,是浏览器先向目的Servlet发送一次Request请求,然后在服务器端由Servlet再将请求发送到目的url,再由服务器端Servlet返回response到浏览器端。浏览器和服务器一次请求响应。
     使用sendRedirect转发的过程,浏览器先向目的Servlet发送一次请求,Servlet看到sendRedirect将目的url返回到浏览器,浏览器再去请求目的url,目的url再返回response到浏览器。浏览器和服务器两次请求响应。
4.request和response
     forward方法的调用者与被调用者之间共享Request和Response
     sendRedirect方法由于两次浏览器服务器请求,所以有两个Request和Response。
     如果使用request.setAttribute传递一些属性就需要用forward,如果想要跳转到别的应用的资源,就需要用sendRedirect。
5.都不能有PrinterWriter输出到客户端
     无论是forward方法还是sendRedirect方法调用前面都不能有PrintWriter输出到客户端。
     forward方法报错: Java.lang.IllegalStateException: Cannot forward after response has been committed
     sendRedirect报错:java.lang.IllegalStateException  at                org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:435)
 
两张图简单直接:
forward:                                                  sendRedirect:
                          
 
 
ps:他人对forward的看法
今天在调试一个Servlet程序的时候,报了以下错误!
java.lang.IllegalStateException: Cannot forward after response has been committed
根据字面理解的话,意识是在response已经提交后程序不能再一次的跳转!
 
研究代码以后发现,是因为前面已经执行过一次request.request.getRequestDispatcher().forward()
但是后面的request.request.getRequestDispatcher().forward()依然被执行到了!
 
那么很有理由相信request.request.getRequestDispatcher().forward()跳转本身是不会返回什么,也不会终止程序体的执行!
程序体后面该执行的还是会执行!
 
 
 参考:
https://my.oschina.net/abbchina/blog/649274
http://blog.csdn.net/yoxibaga/article/details/8624056
posted @ 2017-09-03 13:14  Morale_U  阅读(892)  评论(0编辑  收藏  举报