JSP-Servlet的工作流程


Servlet基礎

 

  1.Servlet概述

    JSP的前身就是Servlet。Servlet就是在服務器端運行的一段小程序。一個Servlet就是一個Java類,並且可以通過“請求-響應”編程模型來訪問的這個駐留在服務器內存的Servlet程序。

  2.Tomcat容器等級

    Tomcat的容器分為4個等級,Servlet的容器管理Context容器,一個Context對應一個Web工程。

  3.手工編寫第一個Servlet

    編寫一個Servlet程序大體上需要3個步驟:繼承HttpServlet-->重寫doGet()或者doPost()方法-->在web.xml中注冊Servlet。

    HttpServlet的繼承關系如圖:

    重寫doGet還是doPost方法需要根據請求方式而定。

  一、編寫一個類繼承自HttpRequest並重寫doGet(或者doPost方法)在項目的src目錄下新建一個servlet.MyServlet.java

復制代碼
 1 package servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 /** 繼承自HttpServlet */
12 public class HelloServlet extends HttpServlet {
13 
14     /** 重寫doGet方法 */
15     @Override
16     protected void doGet(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18         System.out.println("處理get請求。。。");
19         PrintWriter out = response.getWriter();
20         out.println("<b>HelloServlet</b>");
21     }
22 
23     /** 重寫doPost方法 */
24     @Override
25     protected void doPost(HttpServletRequest request, HttpServletResponse response)
26             throws ServletException, IOException {
27         System.out.println("處理post請求。。。");
28         PrintWriter out = response.getWriter();
29         out.println("<b>HelloServlet</b>");
30     }
31     
32 }
復制代碼

  二、在WEB-INF/web.xml中注冊剛剛新建的Servlet:

復制代碼
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" 
 3     xmlns="http://java.sun.com/xml/ns/javaee" 
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 7   <display-name></display-name>    
 8   <welcome-file-list>
 9     <welcome-file>index.jsp</welcome-file>
10   </welcome-file-list>
11   
12   <!-- 注冊Servlet開始 -->
13   <servlet>
14       <servlet-name>HelloServlet</servlet-name>
15       <servlet-class>servlet.HelloServlet</servlet-class>
16   </servlet>
17   <servlet-mapping>
18       <servlet-name>HelloServlet</servlet-name>
19       <url-pattern>/servlet/HelloServlet</url-pattern>
20   </servlet-mapping>
21   <!-- 注冊Servlet結束 -->
22   
23 </web-app>
復制代碼

  其中servlet-name表示Servlet的名字,servlet-class要寫完成的類的定義(包名.類名),url-pattern表示Servlet的路徑。

  在index.jsp中使用自定義的Servlet處理get和post請求。

復制代碼
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 3 <html>
 4   <head>
 5     <title>手工編寫的第一個Servlet</title>
 6   </head>
 7   
 8   <body>
 9     <h1>第一個Servlet小例子</h1><hr>
10     <a href="servlet/HelloServlet">get方式請求HelloServlet</a><br /><br />
11     <form action="servlet/HelloServlet" method="post">
12         <input type="submit" value="post方式請求HelloServlet" /> 
13     </form>
14   </body>
15 </html>
復制代碼

 發布項目,運行結果:

   一個Servlet可以在web.xml中配置多個映射,這樣就可以在URL中使用不同的名字訪問相同的Servlet。如下所示:就可以使用給人以假象——好像使用的是asp或者php或者更多的語言。

復制代碼
 1 <!-- 注冊Servlet開始 -->
 2 <servlet>
 3     <servlet-name>HelloServlet</servlet-name>
 4     <servlet-class>servlet.HelloServlet</servlet-class>
 5 </servlet>
 6 <!-- 一個Servlet可以配置多個映射,向下面這樣配置就可以有多種方式訪問Servlet了 -->
 7 <servlet-mapping>
 8   <servlet-name>HelloServlet</servlet-name>
 9   <url-pattern>/servlet/HelloServlet</url-pattern>
10 </servlet-mapping>
11  <servlet-mapping>
12   <servlet-name>HelloServlet</servlet-name>
13   <url-pattern>/servlet/HelloServlet.asp</url-pattern>
14 </servlet-mapping>
15  <servlet-mapping>
16   <servlet-name>HelloServlet</servlet-name>
17   <url-pattern>/servlet/HelloServlet.php</url-pattern>
18 </servlet-mapping>
19  <servlet-mapping>
20   <servlet-name>HelloServlet</servlet-name>
21   <!-- *表示任意名稱均可 -->
22   <url-pattern>/servlet/hello/*</url-pattern>
23 </servlet-mapping>
24 <!-- 注冊Servlet結束 -->
復制代碼

  4.使用MyEclipse編寫Servlet

      1.src-->new Servlet。

      2.重寫doGet()或者doPost()方法。  

      3.部署運行。

   通過MyEclipse創建Servlet的時候它默認繼承自HttpServlet。默認勾選覆寫init()、destory()、doGet()和doPost()方法,並且自動向web.xml中注冊該Servlet。

   可以發現使用MyEclipse創建的Servlet它已經自動為我們生成了輸出的html模板,我們只需要做很少的改動即可。   

  5.Servlet的執行流程和生命周期

    用戶點擊超鏈接向Servlet發送請求-->服務器在web.xml中的servlet-mapping尋找與該Servlet相對應的URL地址-->找到對應的Servlet名字-->根據Servlet的名字找到和該Servlet相關的處理類-->根據請求的方式不同確定是調用doGet還是doPost方法。

    一個Servlet的生命周期大致分為3個階段:

  

    1.客戶端發送請求給服務器。

    2.服務器開始接受,先判斷該請求的servlet實例是否存在,如果不存在先裝載一個servlet類並創建實例。

        如果存在則直接調用該servlet的service方法,之后進行判斷是調用  doGet方法還是doPost方法。

    3.servlet創建實例后,調用init方法進行初始化。之后調用servce方法,判斷是調用doGet方法還是doPost方法。

      4.最后判斷服務器是否關閉,如果關閉則調用destroy方法。

 

  下面這個例子展示了Servlet的生命周期:

首先是一個Servlet:TestServlet1

復制代碼
 1 package servlet;
 2 
 3 import java.io.IOException;
 4 import java.io.PrintWriter;
 5 
 6 import javax.servlet.ServletException;
 7 import javax.servlet.http.HttpServlet;
 8 import javax.servlet.http.HttpServletRequest;
 9 import javax.servlet.http.HttpServletResponse;
10 
11 public class TestServlet1 extends HttpServlet {
12 
13     public TestServlet1() {
14         System.out.println("TestServlet1構造方法被執行!");
15     }
16 
17     public void destroy() {
18         System.out.println("TestServlet1銷毀方法被執行!");
19     }
20 
21     public void doGet(HttpServletRequest request, HttpServletResponse response)
22             throws ServletException, IOException {
23 
24         System.out.println("TestServlet1的doGet方法被執行!");
25         response.setContentType("text/html;charset=utf-8");
26         PrintWriter out = response.getWriter();
27         out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
28         out.println("<HTML>");
29         out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
30         out.println("  <BODY>");
31         out.println("<h1>你好我是TestServlet1</h1>");
32         out.println("  </BODY>");
33         out.println("</HTML>");
34         out.flush();
35         out.close();
36     }
37 
38     public void doPost(HttpServletRequest request, HttpServletResponse response)
39             throws ServletException, IOException {
40         System.out.println("TestServlet1的doPost方法被執行!");
41         doGet(request, response);// 讓doPost與doGet執行相同的操作
42     }
43 
44     public void init() throws ServletException {
45         System.out.println("TestServlet1的初始化方法被執行!");
46     }
47 
48 }
復制代碼

    主頁index.jsp

復制代碼
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     <title>Servlet的生命周期</title>
12   </head>
13   
14   <body>
15       <h1>Servlet的生命周期</h1><hr />
16       <a href = "servlet/TestServlet1">以get方式請求TestServlet1</a>
17   </body>
18 </html>
復制代碼

  當服務器啟動之后我們第一次訪問index.jsp的時候,構造方法,初始化方法和doGet()方法執行

    當我們再次請求該頁面的時候,只有doGet()方法被執行:

    服務器關閉的時候銷毀方法執行。

 6.Tomcat裝載Servlet的3種情況

    在下列時刻Servlet容器會加載Servlet:

    1.Servlet容器啟動時自動裝載某些Servlet,實現它只需要在web.xml文件中的<servlet></servlet>之間添加以下代碼:

<load-on-startup>1</load-on-startup>

  其中,數字越小表示優先級越高。

    例如:我們在web.xml中設置TestServlet2的優先級為1,而TestServlet1的優先級為2,啟動和關閉Tomcat:

  優先級高的先啟動也先關閉。

    2.客戶端首次向某個Servlet發送請求。【例子詳見Servlet生命周期的那個例子】?//JSP自動會生成Servlet是為了生成動態的HTML頁面流,以便瀏覽器引擎轉化成網頁,同時也是為了與Servlet類進行交換數據。

            //JSP—>servlet發送request時候需要寫入相應servlet的地址,{一種通過JSP文件里使用跳轉標簽指明處理該JSP處理的servlet,或者在servlet中通過@WEBSERVLET進行注射}

           web.xml文件只備注servlet,filter等等類的信息。但是這些不是給備注JSP與Servlet對應關系的信息。所以,jsp與servlet對應關系的地址需要在程序里寫入,容器引擎我會根據地址自動處理。 //servlet—>jsp發送消息也需要寫入{或者通過request重新跳轉到一個JSP}

    3.Servlet類被修改后,Tomcat容器會重新裝載Servlet。

    Servlet被裝載后,Servlet容器會創建一個Servlet實例,並且調用Servlet的init()方法進行初始化,在Servlet的真個生命周期內init()方法只被調用一次。

  7.Servlet與JSP內置對象的對應關系

  8.Servlet獲取表單數據

    用戶在reg.jsp中填寫注冊表單,使用post方式將數據發送到一個名稱為servlet.RegServlet的Servlet處理【Servlet的doPost()方法】,Servlet將用戶信息封裝成一個Users對象存儲在session中,講請求轉發到userinfo.jsp。在userinfo.jsp中通過<jsp:useBean>指令從session中取出保存的用戶對象,通過<jsp:getPerproty>指令顯示用戶對象的各個字段。

  用戶實體entity.Users.java
  注冊頁reg.jsp
  用戶信息顯示頁userinfo.jsp
  處理用戶注冊的Servlet:RegServlet

  9.Servlet路徑跳轉

    相對路徑就是相對於當前頁面的路徑,絕對路徑就是相對於項目根目錄的路徑(絕對路徑需要使用到path變量)。

復制代碼
 1 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
 2 <%
 3 String path = request.getContextPath();
 4 String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
 5 %>
 6 
 7 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 8 <html>
 9   <head>
10     <base href="<%=basePath%>">
11     <title>Servlet路徑跳轉</title>
12   </head>
13   
14   <body>
15     <h1>Servlet路徑跳轉</h1>
16     <!-- 使用相對路徑訪問HelloServlet -->
17     <a href="servlet/HelloServlet">使用相對路徑訪問servlet</a><br />
18     
19     <!-- 使用絕對路徑訪問HelloServlet,使用path變量 -->
20     項目的根目錄:<%=path %><br />
21     <a href="<%=path %>/servlet/HelloServlet">使用相對路徑訪問servlet</a><br />
22   </body>
23 </html>
復制代碼

  在web.xml中注冊的Servlet的路徑寫法是絕對路徑:

復制代碼
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <web-app version="2.5" 
 3     xmlns="http://java.sun.com/xml/ns/javaee" 
 4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 5     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
 6     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 7   <display-name></display-name>
 8   
 9   <!-- Servlet注冊開始 -->
10   <servlet>
11     <description>This is the description of my J2EE component</description>
12     <display-name>This is the display name of my J2EE component</display-name>
13     <servlet-name>HelloServlet</servlet-name>
14     <servlet-class>servlet.HelloServlet</servlet-class>
15   </servlet>
16   <servlet-mapping>
17     <servlet-name>HelloServlet</servlet-name>
18     <url-pattern>/servlet/HelloServlet</url-pattern><!-- Servlet的路徑是絕對路徑 -->
19   </servlet-mapping>
20   <!-- Servlet注冊結束 -->
21       
22   <welcome-file-list>
23     <welcome-file>index.jsp</welcome-file>
24   </welcome-file-list>
25 </web-app>
復制代碼

  在Servlet之中路徑的跳轉問題:

    index.jsp中有一個鏈接指向servlet.TestServlet

<a href="servlet/TestServlet">訪問TestServlet,跳轉到Test.jsp</a>

    servlet.TestServlet的doPost()和doGet()方法如下:

復制代碼
 1 public void doGet(HttpServletRequest request, HttpServletResponse response)
 2             throws ServletException, IOException {
 3 
 4             doPost(request, response);
 5     }
 6 
 7     public void doPost(HttpServletRequest request, HttpServletResponse response)
 8             throws ServletException, IOException {
 9         // 1.使用請求重定向的方式跳轉到test.jsp
10 //        response.sendRedirect("../test.jsp");
11         // 也可以使用絕對路徑的方式request.getContextPath
12 //        response.sendRedirect(request.getContextPath()+"/test.jsp");
13         
14         // 2.使用服務器內部跳轉的方式
15 //        request.getRequestDispatcher("../test.jsp").forward(request, response);
16         request.getRequestDispatcher("/test.jsp").forward(request, response);
17     }
復制代碼

  在TestServlet中完成到網站根目錄下的跳轉有兩種方式重定向和服務器內部轉發,其中URL的寫法也有2種方式:絕對路徑和相對路徑。相對路徑使用..即可,而絕對路徑重定向需要依賴request.getContextPath()方法取得上下文環境,而服務器內部轉發中的斜線就表示項目的根目錄。

  開發中一般在web.xml中配置Servlet的路徑為表單所在路徑,這樣在表單中只需要書寫Servlet名字即可。在開發中應該盡量避免../的寫法。

  10.階段案例——使用Servlet完成用戶登錄

用戶名和密碼都是admin,登陸成功則使用服務器內部轉發到login_success.jsp,顯示登錄成功的用戶名。登錄失敗則重定向到login_failure.jsp。

  把login.jsp中表單的action屬性改為需要處理登錄的Servlet

1 <form action="servlet/LoginServlet" method="post" name="loginForm">
2     <!-- 代碼省略 -->
3 </form>
  用戶實體類org.po.Users
  處理用戶登錄的LoginServlet

 

Servlet高級

  1.獲取初始化參數

    在web.xml中配置Servlet時,可以配置一些初始化參數。而在Servlet中可以通過ServletConfig接口提供的方法來取得這些參數。

    1.首先在index.jsp中建立一條超鏈接指向servlet.GetInitParameterServlet。

<a href = "servlet/GetInitParameterServlet">獲取Servlet的初始化參數</a>

    2.在web.xml中配置該Servlet的初始化參數:

  web.xml

    3.在GetInitParameterServlet的init方法中使用this.getgetInitParameter(String name)方法獲得初始化參數:

  servlet.GetInitParameterServlet.java

運行結果:

  2.MVC模式

  MVC旨在分離模型、視圖、控制。是分層思想的一種體現。

結構圖如下:

  1.瀏覽器發送請求被控制器接收(Servlet)。

  2.由控制器實例化一個模型層對象(JavaBean),模型層訪問EIS(企業信息系統,就是DB)。EIS將結果返回給JavaBean,JavaBean將結果返回給控制層Servlet。

  3.控制層根據模型層返回的結果選擇合適的視圖給用戶呈現。

  3.Model2簡介

  Model2實際上就是JSP(V)+Servlet(C)+JavaBean(M),是MVC設計思想。

  4.階段項目:使用MVC實現購物車

JSP(View)+Servlet(Control)+ dao(Model)。

已有的商品實體類:

  Items.java

實現階段:創建購物車類-->編寫Servlet-->創建頁面層。

  1.購物車類Cart的設計:

  購物車有2個屬性,分別是購買商品的集合和商品的總價格。

  購物車的方法有3個:添加商品、刪除商品、計算商品的總價格。

  那么問題來了,我們應該使用何種集合來存儲用戶購買的商品?我們可以使用Map類型,鍵是商品對象,值是該種商品的數量。

實現如下:

  Cart.java

接下來測試上面的購物車類:

  直接在給Cart類中編寫main方法測試購物車類;

復制代碼
 1 public static void main(String[] args) {
 2         //創建2個商品對象
 3         Items i1 = new Items(1, "沃特籃球鞋", "溫州", 200, 500, "001.jpg");
 4         Items i2 = new Items(2, "李寧運動鞋", "廣州", 300, 500, "002.jpg");
 5         Items i3 = new Items(1, "沃特籃球鞋", "溫州", 200, 500, "001.jpg");
 6         
 7         //創建購物車對象
 8         Cart cart = new Cart();
 9         cart.addGoodsInCart(i1, 1);
10         cart.addGoodsInCart(i2, 2);
11         cart.addGoodsInCart(i3, 3);//再買3雙沃特籃球鞋
12         
13         
14         //購物車中商品的集合
15         Set<Map.Entry<Items, Integer>>items = cart.getGoods().entrySet();
16         for (Map.Entry<Items, Integer> entry : items) {
17             System.out.println(entry);
18         }
19         System.out.println("買4雙沃特籃球鞋和2雙李寧運動鞋之后,購物車總價格:"+cart.getTotalPrice());;
20 }
復制代碼

  運行結果:

 

 雖然總金額的計算沒有問題,但是用戶體驗不太好,購物車中中出現了相同的商品記錄(應該是需要合並的)。

 一種方式是重寫Items類的hashCode和equals方法。重寫之后再次運行程序:

  雖然商品的記錄在購物車中不會重復,但是購買的數量卻不對了,沃特籃球鞋的后面的一條記錄替換掉了前面的記錄。

  解決方案:此時只要修改購物車的addGoodsInCart()方法就行了:在加入新的商品之前先判斷如果已經添加了相同的商品,只需要修改商品的數量即可:

復制代碼
 1 public boolean addGoodsInCart(Items item, int number) {
 2         //如果商品已經在購物車中只需要修改商品數量即可【原有數量+新加入的數量】
 3         if (goods.containsKey(item)) {
 4             goods.put(item, goods.get(item)+number);
 5         }else {
 6             goods.put(item, number);
 7         }
 8         calcTotalPrice();// 重新計算購物車的總金額
 9         return true;
10 }
復制代碼

  運行結果:

  2.Servlet類的設計

    由Servlet類調用購物車類的代碼實現購物功能。

  CartServlet

  3.界面層在details.jsp頁面中顯示購物車。

  details.jsp

  項目的完整地址:https://git.oschina.net/gaopengfei/JavaWebShoppingDemoByMVC.git

 
 
標簽:  javajava webServlet


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM