接上文深入淺出Java MVC(Model View Controller) ---- (JSP + servlet + javabean實例)
,聰明的你肯定會發(fā)現(xiàn)上篇文章的這個內(nèi)容康辑,見Servlet控制層代碼:
import java.text.*;
import java.util.*;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import com.bjpowernode.exam.model.*;
import com.bjpowernode.exam.manager.*;
public class SearchStudentServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sBeginDate = request.getParameter("beginDate");
String sEndDate = request.getParameter("endDate");
Date beginDate = new Date();
Date endDate = new Date();
try {
beginDate = new SimpleDateFormat("yyyy-MM-dd").parse(sBeginDate);
? endDate = new SimpleDateFormat("yyyy-MM-dd").parse(sEndDate);
}catch(Exception e) {
e.printStackTrace();?
}?
StudentManager studentManager = new StudentManagerImpl();
List<Student> studentList = studentManager.findStudentList(beginDate, endDate);
//將學生列表設置到requet范圍中
//request.setAttribute("student_list", studentList);
//轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)是在服務器端轉(zhuǎn)發(fā)的咐吼,客戶端是不知道的
//request.getRequestDispatcher("/student_list.jsp").forward(request, response);
//將studentList放到session中
HttpSession session = request.getSession();
session.setAttribute("student_list", studentList);
//重定向,不會共享request
//以下寫法錯誤,該 "/"代表了8080端口
//response.sendRedirect("/student_list.jsp");
response.sendRedirect(request.getContextPath() + "/student_list.jsp");
}
}
這個里面嘗試了兩種調(diào)到后面的Jsp方法冈止,在servlet中調(diào)用轉(zhuǎn)發(fā)岳瞭、重定向的語句如下:
? ? 實現(xiàn)轉(zhuǎn)發(fā):
//轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)是在服務器端轉(zhuǎn)發(fā)的拥娄,客戶端是不知道的
request.getRequestDispatcher("/student_list.jsp").forward(request, response);
分析:請求轉(zhuǎn)發(fā)是服務器內(nèi)部把對一個request/response的處理權,移交給另外一個對于客戶端而言瞳筏,它只知道自己最早請求的那個A稚瘾,而不知道中間的B,甚至C姚炕、D摊欠。 傳輸?shù)男畔⒉粫G失。
? ? 實現(xiàn)重定向:
//重定向柱宦,不會共享request
//以下寫法錯誤,該 "/"代表了8080端口
response.sendRedirect("/student_list.jsp");
response.sendRedirect(request.getContextPath() + "/student_list.jsp");
深入(分析理解)
? ? 轉(zhuǎn)發(fā)過程
? ? 客戶首先發(fā)送一個請求到服務器端些椒,服務器端發(fā)現(xiàn)匹配的servlet,并指定它去執(zhí)行掸刊,當這個servlet執(zhí)行完之后免糕,它要調(diào)用getRequestDispacther()方法,把請求轉(zhuǎn)發(fā)給指定的student_list.jsp,整個流程都是在服務器端完成的痒给,而且是在同一個請求里面完成的舵稠,因此servlet和jsp共享的是同一個request抱虐,在servlet里面放的所有東西锻梳,在student_list中都能取出來拳锚,因此谁尸,student_list能把結果getAttribute()出來错忱,getAttribute()出來后執(zhí)行完把結果返回給客戶端霍弹。整個過程是一個請求谒撼,一個響應楼咳。
? ? 重定向過程
? ? 客戶發(fā)送一個請求到服務器熄捍,服務器匹配servlet,這都和請求轉(zhuǎn)發(fā)一樣母怜,servlet處理完之后調(diào)用了sendRedirect()這個方法余耽,這個方法是response的方法,所以苹熏,當這個servlet處理完之后碟贾,看到response.senRedirect()方法,立即向客戶端返回這個響應轨域,響應行告訴客戶端你必須要再發(fā)送一個請求袱耽,去訪問student_list.jsp,緊接著客戶端受到這個請求后干发,立刻發(fā)出一個新的請求朱巨,去請求student_list.jsp,這里兩個請求互不干擾,相互獨立枉长,在前面request里面setAttribute()的任何東西冀续,在后面的request里面都獲得不了琼讽。可見洪唐,在sendRedirect()里面是兩個請求跨琳,兩個響應。
淺出(表象)
? ? 轉(zhuǎn)發(fā)
? ? 當用RequestDispatcher請求轉(zhuǎn)發(fā)后桐罕,地址欄為http://localhost:8080/test/TestServlet
這真好應正了上面的分析脉让,我們起初請求的就一個servlet,至于你服務器端怎么轉(zhuǎn)功炮,流程怎么樣的溅潜,我客戶端根本就不知道,我發(fā)了請求后我就等著響應薪伏,那你服務器那邊愿意怎么轉(zhuǎn)就怎么轉(zhuǎn)滚澜,我客戶端不關心也沒法知道,所以當服務器端轉(zhuǎn)發(fā)到jsp后嫁怀,它把結果返回給客戶端设捐,客戶端根本就不知道你這個結果是我真正訪問的servlet產(chǎn)生的,還是由servlet轉(zhuǎn)發(fā)后下一個組件產(chǎn)生的塘淑。
? ? 重定向
? ? 當用sendRedirect重定向后萝招,地址欄為http://localhost:8080/test/student_list.jsp
因為這個時候,客戶端已經(jīng)知道了他第二次請求的是student_list.jsp存捺,服務器已經(jīng)告訴客戶端要去訪問student_list.jsp了槐沼,所以地址欄里會顯示想要訪問的結果。
總結
轉(zhuǎn)發(fā)在服務器端完成的捌治;重定向是在客戶端完成的
轉(zhuǎn)發(fā)的速度快岗钩;重定向速度慢
轉(zhuǎn)發(fā)的是同一次請求;重定向是兩次不同請求
轉(zhuǎn)發(fā)不會執(zhí)行轉(zhuǎn)發(fā)后的代碼肖油;重定向會執(zhí)行重定向之后的代碼
轉(zhuǎn)發(fā)地址欄沒有變化兼吓;重定向地址欄有變化
轉(zhuǎn)發(fā)必須是在同一臺服務器下完成;重定向可以在不同的服務器下完成
? ? Forward是在服務器端的跳轉(zhuǎn)森枪,就是客戶端一個請求發(fā)給服務器视搏,服務器直接將請求相關的參數(shù)的信息原封不動的傳遞到該服務器的其他jsp或servlet去處理,而sendredirect是在客戶端的跳轉(zhuǎn)疲恢,服務器會返回給客戶端一個響應報頭和新的URL地址凶朗,原來的參數(shù)什么的信息如果服務器端沒有特別處理就不存在了,瀏覽器會訪問新的URL所指向的servlet或jsp显拳,這可能不是原先服務器上的webservce了棚愤。