一、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,如下圖所示 。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1UTO1EDN1ADM4ADNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2、右擊資料包“servlet”會彈出如下的快捷菜單,如下圖所示。
3、單擊“new->Servlet”指令,這時會彈出建立servlet的對話框,并在對話框中輸入“Class name”,輸入InsertLogin如下圖所示。
4、單擊“Finish”按鈕結束Servlet檔案的建立,這時在servlet資料包中就顯示我們建立的檔案了。如下圖所示。
同時在代碼區中系統為我們自動生成了很多代碼,代碼如下。
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、單擊工具欄的的“運作”按鈕,運作結果如下。
六、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接口