官术网_书友最值得收藏!

3.9 Servlet間協作

當Web容器接收到客戶端的請求后,它負責創建HttpRequest對象和HttpResponse對象,然后將這兩個對象以參數的形式傳遞給與請求URL地址相關聯的Servlet的service方法進行處理。但對于復雜的處理過程,僅僅通過一個Servlet來實現對于請求的處理往往比較困難,這時經常需要幾個Servlet間共同協作完成對于請求的處理,也就是說,在一個Servlet處理過程中或處理完畢后,將客戶端的請求傳遞到另外一個Servlet來處理,這種像接力賽似的過程稱為請求指派。為實現請求指派,Servlet規范定義了一個接口:javax.servlet.requestdispatcher。

Requestdispatcher封裝了到同一Web應用內的另外一個資源的引用。可以通過調用Requestdispatcher的forword方法將請求傳遞到其他資源,或者調用Requestdispatcher的include方法將其他資源對此請求的響應包含進來。

下面通過一個簡單的登錄系統來演示如何利用Requestdispatcher對象來實現Servlet間的協作。系統后臺功能主要由三個Servlet來實現。Main為主控Servlet,用來實現登錄驗證功能,并根據驗證結果將請求轉發到LoginSuccess或LoginFail, LoginSuccess處理登錄成功條件下的請求處理,LoginFail處理登錄失敗條件下的請求處理。

首先生成登錄信息提交頁面。代碼如程序3-29所示。

程序3-29:dl.html

    <html lang='zh'>
      <head>
    <title>登錄</title>
    </head>
    <body bgcolor="#FFFFFF">
    <center>歡迎登錄系統</center>
    <form name="login" method="post"  action="Main">
    <label>用戶名:</label>
    <input type=text name="userID" value="">
    <label>密碼:</label>
    <input type=password name="password" value="">
    <input type="submit" name="tj" value ="提交" ></input>
    <input type="reset" name="reset" ></input>
    </form>
    </body>
    </html>

程序說明:頁面模擬一個系統登錄頁面,用戶名和密碼信息通過表單提交到后臺的Servlet處理。

下面生成主控Servlet Main。代碼如程序3-30所示。

程序3-30:Main.java

    package example.servlet;
    …
    @WebServlet(name=" Main ", urlPatterns={"/ Main "})
    public class Main extends HttpServlet {
        protected void processRequest(HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
            String userID=request.getParameter("userID");
            if(userID==null)userID="";
            String password=request.getParameter("password");
            if(password==null)password="";
            if((userID.equals("guest")&&password.equals("guest"))){
              RequestDispatcher dispatcher =
                      request.getRequestDispatcher("LoginSuccess");
              dispatcher.forward(request, response);
            } else{
              RequestDispatcher dispatcher =
                      request.getRequestDispatcher("LoginFail");
              dispatcher.forward(request, response);
            }
          }
        …
       }

程序說明:首先調用Request對象的getParameter方法來獲取登錄頁面提交的信息,然后根據提交的信息進行登錄驗證(為表述簡單,這里只是用它來與固定值guest進行對比)。通過調用HttpServletRequest對象的getRequestDispatcher方法來得到其他Web組件對應的RequestDispatcher對象,其中getRequestDispatcher方法的參數為被請求指派資源在部署描述文件中的URL地址。最后調用RequestDispatcher對象的forward方法,將請求導向其他Servlet組件。

下面生成登錄成功條件下的指派資源Servlet LoginSuccess和登錄失敗條件下的指派資源Servlet LoginFail,代碼如程序3-31和程序3-32所示。

程序3-31:LoginSuccess.java

    package example.servlet;
    …
    @WebServlet(name=" LoginSuccess ", urlPatterns={"/ LoginSuccess "})
    public class LoginSuccess extends HttpServlet {
        protected void processRequest(HttpServletRequest request,
        HttpServletResponse response)
        throws ServletException, IOException {
          response.setContentType("text/html; charset=UTF-8");
          PrintWriter out = response.getWriter();
          String name=request.getParameter("userID");
          out.println("<html>");
          out.println("<head>");
          out.println("<title>登錄成功</title>");
          out.println("</head>");
          out.println("<body>");
          out.println("<h1>歡迎!"+name+"您已成功登錄系統...</h1>");
            out.println("</body>");
            out.println("</html>");
            out.close();
        }
        …
        }

程序說明:作為登錄驗證成功的響應,顯示一條歡迎信息。由于RequestDispatcher對象forward方法將前端的請求對象request傳遞到本Servlet,因此,依然可以調用request對象的getParameter("userID")方法來獲取用戶的登錄ID。用戶請求對象的生命周期直到服務器端向客戶端返回響應時才宣告結束。

程序3-32:LoginFail.java

    package example.servlet;
    …
    @WebServlet(name=" LoginFail ", urlPatterns={"/ LoginFail "})
    public class LoginFail extends HttpServlet {
     protected void processRequest(HttpServletRequest request, HttpServletResponse
     response)
        throws ServletException, IOException {
          response.setContentType("text/html; charset=UTF-8");
          RequestDispatcher dispatcher = request.getRequestDispatcher
          ("login.html");
          dispatcher.include(request, response);
            }
      …
        }

程序說明:作為登錄驗證失敗的響應,調用RequestDispatcher對象的include方法,將登錄頁面作為響應的一部分輸出到客戶端顯示。

保存程序并重新發布Web應用,打開IE瀏覽器,在地址欄中輸入http:/localhost:8080/Chapter3/dl.html,得到如圖3-34所示的運行結果頁面。在“用戶名”文本框輸入guest,在“密碼”文本框輸入guest,單擊“提交”按鈕,則得到如圖3-35所示的頁面,可以看到請求被指派給了Servlet LoginSuccess。單擊瀏覽器上的“后退”按鈕,分別在“用戶名”文本框和“密碼”文本框輸入其他數據并再次提交,則得到如圖3-36所示的運行結果頁面,可以看到請求被指派給了Servlet LoginFail。仔細觀察圖3-35和圖3-36中瀏覽器的地址欄顯示,可以看到地址欄中顯示的是同一個地址,這是因為請求指派是在服務器端進行的,因此在客戶端的瀏覽器上覺察不到。

圖3-34 登錄頁面

圖3-35 登錄成功頁面

圖3-36 登錄失敗頁面

在3.5節中了解到可以通過HttpServletResponse的sendRedirect實現請求重定向,那么它與調用RequestDispatcher的forward方法有什么區別呢?

首先,從操作的本質上,RequestDispatcher的forward是容器中控制權的轉向,在客戶端瀏覽器地址欄中不會顯示出轉向后的地址;而HttpServletResponse的sendRedirect是完全的跳轉,瀏覽器將會得到跳轉的地址,并重新發送請求連接。這樣,從瀏覽器的地址欄中可以看到跳轉后的鏈接地址。其次,從性能上,前者仍舊是在同一次請求處理過程中,后者是結束第一次請求,由瀏覽器發起一次新的請求,因此,RequestDispatcher的forward更加高效。在條件許可時,開發人員盡量使用RequestDispatcher的forward方法。

RequestDispatcher的forward也有局限,它只能轉到Web應用內部的資源,而在有些情況下,比如,需要跳轉到其他服務器上的某個資源時,則必須使用HttpServletResponse的sendRedirect方法。

Servlet中有兩種方式獲得轉發對象(RequestDispatcher):一種是通過HttpServletRequest的getRequestDispatcher方法獲得,一種是通過ServletContext的getRequestDispatcher方法獲得。

重定向的方法只有一種:HttpServletResponse的sendRedirect方法。

這三個方法的參數都是一個URL形式的字符串,但在使用相對路徑或絕對路徑上有所區別。

(1)HttpServletResponse.sendRedirect(String)

參數可以指定為相對路徑、絕對路徑或其他Web應用。假設以http://localhost/myApp/cool/from.do作為起點。

若采用相對路徑,代碼為response.sendRedirect(" foo/to.do "),則容器相對于原來請求URL的目錄加上sendRedirect參數來生成完整的URL:http://localhost/myApp/cool/foo/to.do

若采用絕對路徑,代碼為response.sendRedirect(" / foo/to.do "),容器相對于Web服務器本身加sendRedirect參數生成完整的URL:http://localhost/foo/to.do

若參數為其他Web應用資源,如response.sendRedirect("

(2)HttpServletRequest.getRequestDispatcher(String)

參數可以指定為相對路徑或絕對路徑。相對路徑情況下生成的完整URL與重定向方法相同。絕對路徑與重定向不同,容器將相對于Web應用的根目錄加參數生成完整的URL,即:request.getRequestDispatcher("/foo/to.do")生成的URL是http://localhost/myApp/foo/to.do

(3)ServletContext.getRequestDispatcher(String)

參數只能指定為絕對路徑,生成的完整URL與HttpServletRequest.getRequestDispatcher (String)相同。

主站蜘蛛池模板: 仁怀市| 巴南区| 崇义县| 商城县| 泸定县| 贵德县| 鸡泽县| 神木县| 若尔盖县| 湖南省| 霸州市| 蕉岭县| 贡嘎县| 大石桥市| 麦盖提县| 湘阴县| 浙江省| 奉化市| 白城市| 长乐市| 金平| 德令哈市| 保德县| 和顺县| 玉屏| 那曲县| 罗田县| 德惠市| 海阳市| 维西| 西贡区| 盐城市| 花垣县| 共和县| 收藏| 阿图什市| 浮山县| 井冈山市| 康乐县| 腾冲县| 剑川县|