web 前段與後端的互動(JSP 和 Servlet)
說到web前後端(分離)進行互動,很可能會想到MVC。
那什麼是MVC???
表現層、中間層(控制層、業務邏輯層)和資料服務層
MVC:是模型(model)-檢視(view)-控制器(controller)的縮寫
JSP與servlet 區別和聯絡:
如圖所示,Java提供一系列介面類(所謂介面類就是類中所有方法只提供方法宣告,不提供任何的方法實現,這些類的實現就留給後繼者去做。):Servlet、ServletConfig、Serializable,然後通過多重繼承產生一個最通用的Servlet實現類(圖中Gerneric Servlet類),接下來,通過一個多重繼承與實現,產生一個新的實現類HttpServlet,使用者在開發Servlet程式時只需繼承這個類,從而產生一個自己的類(圖中Hello_Servlet類),然後根據實際開發功能與資訊處理需要,去實現該類中的相關方法即可。這就是前面提到的按照Servlet規範編寫一個Java類,從而編寫一個Servlet。
至於JSP(JavaServlet Page)從圖中可以看出,實際上它也是從Servlet繼承而來。只不過它在Servlet當中又新增/修改了一些方法,作了新的封裝。具體到Tomcat Web應用伺服器中,它通過一個多重繼承,分別從Java的HttpJspPage和HttpServlet兩個類那裡繼承和實現一些方法,然後封裝一個叫做HttpJspBase的類從而實現了一個通用化的JSP類,使用者在開發自己的JSP時,只需要從HttpJspBase繼承一個自己的類(如圖中Hello_jsp類),然後根據需要去實現相應的方法即可。
因此這也是為什麼JSP的程式碼中總是閃現Servlet程式碼框架影子的原因,其實它們只是為實現同樣的功能而進行了不同封裝的元件而已,血脈裡留著的是一樣的血。
請求轉發與請求重定向的比較:
深入(分析理解)
轉發過程
客戶首先發送一個請求到伺服器端,伺服器端發現匹配的servlet,並指定它去執行,當這個servlet執行完之後,它要呼叫getRequestDispacther()方法,把請求轉發給指定的student_list.jsp,整個流程都是在伺服器端完成的,而且是在同一個請求裡面完成的,因此servlet和jsp共享的是同一個request,在servlet裡面放的所有東西,在student_list中都能取出來,因此,student_list能把結果getAttribute()出來,getAttribute()出來後執行完把結果返回給客戶端。整個過程是一個請求,一個響應。
重定向過程
客戶傳送一個請求到伺服器,伺服器匹配servlet,這都和請求轉發一樣,servlet處理完之後呼叫了sendRedirect()這個方法,這個方法是response的方法,所以,當這個servlet處理完之後,看到response.senRedirect()方法,立即向客戶端返回這個響應,響應行告訴客戶端你必須要再發送一個請求,去訪問student_list.jsp,緊接著客戶端受到這個請求後,立刻發出一個新的請求,去請求student_list.jsp,這裡兩個請求互不干擾,相互獨立,在前面request裡面setAttribute()的任何東西,在後面的request裡面都獲得不了。可見,在sendRedirect()裡面是兩個請求,兩個響應。
淺出(表象)
轉發
當用RequestDispatcher請求轉發後,位址列為http://localhost:8080/test/TestServlet
這真好應正了上面的分析,我們起初請求的就一個servlet,至於你伺服器端怎麼轉,流程怎麼樣的,我客戶端根本就不知道,我發了請求後我就等著響應,那你伺服器那邊願意怎麼轉就怎麼轉,我客戶端不關心也沒法知道,所以當伺服器端轉發到jsp後,它把結果返回給客戶端,客戶端根本就不知道你這個結果是我真正訪問的servlet產生的,還是由servlet轉發後下一個元件產生的。
重定向
當用sendRedirect重定向後,位址列為http://localhost:8080/test/student_list.jsp
因為這個時候,客戶端已經知道了他第二次請求的是student_list.jsp,伺服器已經告訴客戶端要去訪問student_list.jsp了,所以位址列裡會顯示想要訪問的結果。
總結:
轉發在伺服器端完成的;重定向是在客戶端完成的
轉發的速度快;重定向速度慢
轉發的是同一次請求;重定向是兩次不同請求
轉發不會執行轉發後的程式碼;重定向會執行重定向之後的程式碼
轉發位址列沒有變化;重定向位址列有變化
轉發必須是在同一臺伺服器下完成;重定向可以在不同的伺服器下完成