天天看點

J2EE 之JavaServlet 一、JavaServlet概述

 一、JavaServlet概述

 什麼是JavaServlet

   JavaServlet是位于Web伺服器内部的、運作于伺服器端的、獨立于平台和協定的Java應用程式(以下簡稱Servlet),可以生成動态的Web。

   Servlet由Web伺服器進行加載,該Web伺服器必須包含支援Servlet的Java虛拟機。

   Servlet的運作需要在web.xml中進行描述和注冊。

二、Servlet的特點

1 .高效性:Servlet采用了多線程的處理機制,有效地節省了處理時間和資源配置設定,提高了處理效率。

2 .開發的友善性:Servlet提供了大量的實用工具例程,使用者可以非常友善地學習并在此基礎上開發出所需的應用程式。

3.強大的功能性:Servlet為使用者提供了許多以往CGI很難實作的功能,這些強大的功能為使用者的Web開發提供了很好的支援。

4.可移植性:Servlet的定義和開發具有完善的标準。是以,Servlet不需修改或隻需簡單調整即可移植到Apache、Microsoft IIS等支援Servlet的Web伺服器上。幾乎所有的主流伺服器都直接或通過插件支援Servlet。

5.安全性:Servlet是由Java編寫的,是以它可以使用Java的安全架構;ServletAPI被實作為類型安全的;容器也會對Servlet的安全進行管理。

三、Servlet程式設計基礎

   Servlet架構由javax.servlet和javax.servlet.http兩個Java包組成。在javax.servlet包中定義了所有的Servlet類都必須實行或擴充的通用接口和類。

   在javax.servlet.http包中定義了采用http通信的HttpServlet類。

  所有的Servlet 對象都要實作Servlet 接口。已經實作了Servlet 接口的javax.servlet.GenericServlet 和javax.servlet.http.HttpServlet 這兩個抽象類的子類來間接實作Servlet 接口。

四、Servlet接口

  使用者編寫的Servlet程式都必須實作javax.servlet.Servlet接口,該接口是ServletAPI的核心,在這個接口中有5個方法必須實作。

init()方法

service()方法

destroy()方法

getServletConfig()方法

getServletInfo()方法

下面進行詳細介紹。

1. init()方法

格式 :public void init(ServletConfig config) throws ServletException

  說明:該方法用于初始化一個Servlet類執行個體,并将其加載到記憶體中。接口規定對任何Servlet執行個體,在一個生命周期中此方法隻能被調用一次。如果此方法沒有正常結束就會抛出一個ServletException異常, 而Servlet不再執行。随後對它的調用會由Servlet容器對它重新載入并再次運作該方法。

2. service()方法

  格式:publicvoid service(ServletRequest req,ServletResponse res) throwsServletException,IOException

說明:Servlet成功初始化後該方法會被調用,用于處理使用者請求。該方法在Servlet生命周期中可執行很多次,每個使用者的請求都會執行一次service()方法,完成與相應用戶端的互動。

3. destroy()方法

  格式:publicvoid destroy()

  說明:該方法用于終止Servlet服務,銷毀一個Servlet執行個體。

4. getServletConfig()方法

  格式:publicServletConfig getServletConfig()

  說明:該方法可獲得ServletConfig對象,裡面包含該Servlet的初始化資訊,如初始化參數和ServletContext對象。

5. getServletInfo()方法

  格式:publicString getServletInfo()

說明:此方法傳回一個String對象,該對象包含Servlet的資訊,例如開發者、建立日期、描述資訊等。

  上述方法中的init()、service()、destroy()方法是Servlet的生命周期方法,由Servlet自動調用,如當伺服器關閉時,就會自動調用destroy()方法。

   實際上,Servlet為使用者提供了兩個更适用于程式設計的抽象類javax.servlet.GenericServlet和 javax.servlet.http.HttpServlet,這兩個抽象類間接實作了Servlet 接口。

   GenericServlet抽象類繼承了Servlet接口并實作了javax.servlet.Servlet接口中除了service()方法以外的其他所有方法,這樣使用者隻需實作一個service()方法即可。

   HttpServlet抽象類則是針對http協定而定義的,是GenericServlet類的子類,它僅支援基于http協定的請求或響應。

五、Servlet程式的編譯

  建立Servlet程式的過程

1、打開Eclipse,然後在Java2e 項目中的java Resources\src目錄中建立一個資料包,包名為servlet,如下圖所示 。

J2EE 之JavaServlet 一、JavaServlet概述

2、右擊資料包“servlet”會彈出如下的快捷菜單,如下圖所示。

J2EE 之JavaServlet 一、JavaServlet概述

3、單擊“new->Servlet”指令,這時會彈出建立servlet的對話框,并在對話框中輸入“Class name”,輸入InsertLogin如下圖所示。

J2EE 之JavaServlet 一、JavaServlet概述

4、單擊“Finish”按鈕結束Servlet檔案的建立,這時在servlet資料包中就顯示我們建立的檔案了。如下圖所示。

J2EE 之JavaServlet 一、JavaServlet概述

同時在代碼區中系統為我們自動生成了很多代碼,代碼如下。

package servlet;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@WebServlet("/InsertLong")  //這是一個注解語句,表示我們要向這個servlet提出請求,我們隻要在位址欄上輸入如下位址“http://localhost:8080/javaeepro/InsertLong”這樣就可向InsertLong送出請求了。當然我們可以在WebContext\WEB-INF\web.xml中進行配置。

public class InsertLong extends HttpServlet {

private static final long serialVersionUID = 1L;       

    public InsertLong() {

        super();

    }

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//下面語句用于向用戶端輸出“Served at ”加上(request.getContextPath())是服務所在路徑。

                response.getWriter().append("Served at: ").append(request.getContextPath());

}

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 下面語句是,把使用者請求轉發給doGet()方法進行處理,從這裡我們知道,不管使用者采用get或是post請求都是統一在doGet()方法中進行處理。

doGet(request, response);

}

}

5、我們要向用該servlet向login資料表添加資料,我們在該檔案中添加如下代碼。

package servlet;

import java.io.IOException;

import java.sql.*;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

@WebServlet("/InsertLong")//這是一個注解語句,表示我們要向這個servlet提出請求,我們隻要在位址欄上輸入如下位址“http://localhost:8080/javaeepro/InsertLong”這樣就可向InsertLong送出請求了。當然我們可以在WebContext\WEB-INF\web.xml中進行配置。

public class InsertLong extends HttpServlet {

private static final long serialVersionUID = 1L;

// 驅動程式

private static final String DBDRIVER = "org.gjt.mm.mysql.Driver";

// 指定資料庫位址

private static final String DBURL = "jdbc:mysql://localhost:3306/stsc";

// 資料庫管理者

private static final String DBUSER = "root";

// 管理者的密碼

private static final String DBPASS = "admin";

// 定義資料庫連接配接對象

private static Connection conn = null;

// 定義一個擷取資料庫連接配接對象的方法

public static Connection getConn() {

try {

Class.forName(DBDRIVER);// 加載資料庫連接配接驅動程式

conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);// 擷取資料庫連接配接對象

return conn;// 傳回資料庫連接配接對象

} catch (Exception e) {

// TODO Auto-generated catch block

return conn;

}

}

public InsertLong() {

super();

// TODO Auto-generated constructor stub

}

protected void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// TODO Auto-generated method stub

try {

conn = getConn();// 擷取資料連接配接對象

if (conn != null) {

//定義向資料表login添加資料的指令

String sql = "insert into login(name,pass) values(?,?)";

//建立執行sql指令的對象

PreparedStatement psta = conn.prepareStatement(sql);

//為指令中的參數指派

psta.setString(1, "zhangsan");

psta.setString(2, "zhangsan");

//執行指令,并儲存選擇的結果,若傳回的結果值是大于0,表示添加資料成功,否則添加資料失敗

int i=psta.executeUpdate();

if(i>0){

response.getWriter().append("添加資料成功 ");

}else{

response.getWriter().append("添加資料失敗 ");

}

}else{

response.getWriter().append("無法打開資料,請聯系管理者 ");

}

} catch (SQLException e) {

// TODO Auto-generated catch block

response.getWriter().append("無法打開資料,請聯系管理者 ");

}

}

protected void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// TODO Auto-generated method stub

doGet(request, response);

}

}

6、單擊工具欄的的“運作”按鈕,運作結果如下。

J2EE 之JavaServlet 一、JavaServlet概述

六、Servlet的生命周期

   每個Servlet都有一個生命周期,該生命周期由建立Servlet執行個體的Servlet容器進行控制。所謂Servlet生命周期就是指Servlet容器建立Servlet執行個體後響應客戶請求直至銷毀的全過程。

  Servlet的生命周期可以分為四個階段:類裝載及執行個體建立階段、執行個體初始化階段、服務階段以及執行個體銷毀階段。

七、與Servlet實作相關的Servlet接口

1、Servlet接口

     該接口定義了如下5個方法 

   ( 1). init() 

    (2). service() 

   (3). destroy() 

   (4). getServletConfig() 

   (5). getServletInfo() 

也就意味着,如果我們要通過實作Servlet接口來編寫Servlet類,需要實作Servlet接口中定義的5個方法,這樣編寫比較麻煩,于是有了抽象類。

2、Servlet抽象類

(1) GenericServlet抽象類

該類定義了一個通用的、不依賴于具體協定的Servlet,他實作了Servlet接口和ServletConfig接口。

由于該類給出了除了service()方法的其他4個方法的簡單實作。是以,通過繼承GenericServlet來編寫Servlet類,隻需要實作service()方法即可。

(2) HttpServlet抽象類

大多數的網絡應用中,都是用戶端通過HTTP協定去通路伺服器端的資源,而我們所編寫的Servlet也主要用于HTTP協定的請求和響應。為了快速開發應用于HTTP協定的Servlet類,Sun公司在javax.servlet.http包中給我們提供了一個抽象的類HttpServlet,它繼承自GenericServlet類,用于建立适合Web站點的HTTP Servlet。

另外,針對HTTP1.1中定義的7種請求方法GET,POST,HEAD,PUT,DELETE,TRACE,OPTIONS,HttpServlet分别提供了7個處理方法: 

doGet(),doPost(),doHead(),doPut(),doDelete(),doTrace(),doOptions() 

當容器接收到一個針對HttpServlet對象的請求時,調用該對象中的方法的順序如下: 

1. 調用公共(public) service()方法。 

2. 在公共的 service() 方法中,首先将參數類型轉換為HttpServletRequest和HttpServletResponse,然後調用保護的(protected) service()方法,将轉換後的HttpServletRequest對象和HttpServletResponse對象作為參數傳遞進去。 

3. 在保護的service()方法中,首先調用HttpServletRequest對象的getMethod()方法,擷取HTTP請求方法的名字,然後跟去請求方法的類型,調用相應的doXxx()方法。

是以我們在編寫HttpServlet派生類的時候,一般不需要去覆寫service()方法,而隻需要重寫相應的doXxx()方法即可。

HttpServlet對這7種方法的實作: 

1. TRACE和OPTIONS做了适當實作,不需要去覆寫。 

2. 其他5個提供的實作都是傳回HTTP錯誤。

3、與請求和響應相關的接口

Servlet由Servlet容器管理,當使用者請求到來時,容器建立一個ServletRequest對象,封裝請求資料,同時建立一個ServletResponse對象,封裝響應資料。這兩個對象被容器作為service()方法的參數傳遞給Servlet,Servlet利用ServletRequest對象擷取用戶端發送來的請求資料,利用ServletResponse對象發送響應資料。

對于HttpServletRequest對象和HttpServletResponse對象分别繼承與ServletRequest對象和ServletResponse對象,并且在原有方法基礎上新增一些方法。但都是用作封裝請求資料和響應資料。

4、與Servlet配置相關的接口

Servlet容器使用ServletConfig對象在Servlet初始化期間向它傳遞配置資訊,一個Servlet隻有一個ServletConfig對象。 

在ServletConfig接口中,隻定義了4個方法: 

(1).getInitParameter() 

(2). getInitParameterNames() 

(3). getServletContext() 

(4). getServletName() 

5、Servlet上下文

運作在Java虛拟機中的每一個Web應用程式都有一個與之相關的Servlet上下文。Java Servlet API提供了一個ServletContext接口用來表示上下文。在這個接口中定義了一組方法,Servlet可以使用這些方法與它的Servlet容器進行通信。例如,得到檔案的MIME類型,轉發請求,或者向日志檔案中寫入日志資訊。 

Servlet容器在Web應用程式加載時建立ServletContext對象,作為Web應用程式的運作時表示,ServletContext對象可以被應用程式中所有的Servlet所通路。

得到ServletContext對象的方法: 

(1). 通過ServletConfig對象的getServletContext()方法得到。 

(2). GenericServlet類的getServletContext()方法得到(其實質也是調用ServletConfig對象的getServletContext()方法得到的)。

6. 請求轉發

實作請求轉發是通過RequestDispatcher接口實作的 

得到RequestDispatcher對象的方法: 

(1). 利用ServletRequest接口中的RequestDispatcher()方法 

(2). 利用ServletContext接口中的getNamedDispatcher()方法 

(3). 利用ServletContext接口中的getRequestDispatcher()方法 

請求轉發的兩種方法: 

(1). forward() 

(2). include() 

兩者差別在于,利用include()方法将請求轉發給其他的Servlet,被調用的Servlet對該請求作出的響應将并入原先的響應對象中,原先的Servlet還可以繼續輸出響應資訊。而利用forward()方法将請求轉發給其他的Servlet,将由被調用的Servlet負責對請求作出響應,而原先Servlet的執行則終止。

另外還可以通過HttpServletResponse接口的sendRedirect()方法利用另外的資源來為用戶端進行服務。

sendRedirect()不但可以在位于同一個主機上的不同Web應用程式之間進行重定向,而且可以将用戶端重定向到其他伺服器上的Web應用程式資源。 

總結

Servlet API 中主要接口及實作類,包括:

與Servlet實作相關的Servlet接口 

Servlet接口

GenericServlet抽象類

HttpServlet抽象類

與請求和響應相關的接口 

ServletRequest接口

ServletResponse接口

HttpServletResquest接口

HttpServletResponse接口

與Servlet配置相關的接口 

ServletConfig接口

Servlet上下文 

ServletContext接口

請求轉發 

RequestDispatcher接口