Servlet是Java提供的用於開發Web服務器應用程序的一個組件,運行在服務器端,由Servlet容器所管理,用於生成動態的內容。Servlet是平臺獨立的Java類,編寫一個Servlet,實際上就是按照Servlet規範編寫一個Java類。html
如圖所示,Java提供一系列接口類(所謂接口類就是類中全部方法只提供方法聲明,不提供任何的方法實現,這些類的實現就留給後繼者去作。):Servlet、ServletConfig、Serializable,而後經過多重繼承產生一個最通用的Servlet實現類(圖中Gerneric Servlet類),接下來,經過一個多重繼承與實現,產生一個新的實現類HttpServlet,用戶在開發Servlet程序時只需繼承這個類,從而產生一個本身的類(圖中Hello_Servlet類),而後根據實際開發功能與信息處理須要,去實現該類中的相關方法便可。這就是前面提到的按照Servlet規範編寫一個Java類,從而編寫一個Servlet。java
至於JSP(JavaServlet Page)從圖中能夠看出,實際上它也是從Servlet繼承而來。只不過它在Servlet當中又添加/修改了一些方法,做了新的封裝。具體到Tomcat Web應用服務器中,它經過一個多重繼承,分別從Java的HttpJspPage和HttpServlet兩個類那裏繼承和實現一些方法,而後封裝一個叫作HttpJspBase的類從而實現了一個通用化的JSP類,用戶在開發本身的JSP時,只須要從HttpJspBase繼承一個本身的類(如圖中Hello_jsp類),而後根據須要去實現相應的方法便可。程序員
所以這也是爲何JSP的代碼中老是閃現Servlet代碼框架影子的緣由,其實它們只是爲實現一樣的功能而進行了不一樣封裝的組件而已,血脈裏留着的是同樣的血。web
「既生瑜何生亮?」呵呵,由於JSP確實比Servlet要更勝一籌,所謂「青出於藍勝於藍」,既然Sun公司要在Servlet基礎上推出JSP技術,那確定是由於JSP有它更高明的地方。數據庫
使用Servlet產生動態網頁,須要在代碼中打印輸出不少HTML的標籤,此外,在Servlet中,咱們不得不將靜態現實的內容和動態產生內容的代碼混合在一塊兒。使用Servlet開發動態網頁,程序員和網頁編輯人員將沒法一塊兒工做,由於網頁編輯人員不瞭解Java語言,沒法修改Servlet代碼,而Java程序員可能也不是很瞭解網頁編輯人員的意圖,以致於沒法修改和實現網頁功能。爲了解決這些問題,Sun公司就推出了JSP技術。express
JSP是Servlet的擴展,在沒有JSP以前,就已經出現了Servlet技術。Servlet是利用輸出流動態生成HTML頁面,包括每個HTML標籤和每一個在HTML頁面中出現的內容。apache
JSP經過在標準的HTML頁面中插入Java代碼,其靜態的部分無須Java程序控制,只有那些須要從數據庫讀取並根據程序動態生成信息時,才使用Java腳本控制。編程
事實上,JSP是Servlet的一種特殊形式,每一個JSP頁面就是一個Servlet實例——JSP頁面由系統編譯成Servlet,Servlet再負責響應用戶請求。JSP其實也是Servlet的一種簡化,使用JSP時,其實仍是使用Servlet,由於Web應用中的每一個JSP頁面都會由Servlet容器生成對應的Servlet。對於Tomcat而言,JSP頁面生成的Servlet放在work路徑對應的Web應用下。數組
以apache-tomcat-7.0.37\webapps\myapp\index.jsp爲例,瀏覽器
當啓動Tomcat以後,能夠在Tomcat的apache-tomcat-7.0.37\work\Catalina\localhost\myapp\org\apache\jsp目錄下找到以下文件:indexd.java和index.class。這兩個文件都是Tomcat生成的,Tomcat根據JSP頁面生成對應Servlet的Java文件及class文件。
index.java
根據上面的JSP頁面工做原理圖,能夠獲得以下結論: JSP文件必須在JSP服務器內運行。JSP文件必須生成Servlet才能執行。每一個JSP頁面的第一個訪問者速度很慢,由於必須等待JSP編譯成Servlet。JSP頁面的訪問者無須安裝任何客戶端,甚至不須要能夠運行Java的運行環境,由於JSP頁面輸送到客戶端的是標準HTML頁面。index.jsp頁面中的每一個字符都由index.java文件的輸出流生成.
servlet是在web服務器上的java程序,它提供服務,由它來傳遞給你html的格式。Servlet API爲Servlet提供了統一的編程接口
Servlet必須部署在Servlet容器,才能響應客戶端的請求 對外提供服務。要對外統一接口,由容器來調用。
jsp側重顯示;servlet側重控制邏輯。
MVC模式:Jsp + Servlet + JavaBean。M-JavaBean V-Jsp C-Servlet
小應用程序(Applet)是指採用Java建立的基於HTML的程序。瀏覽器將其暫時下載到用戶的硬盤上,並在Web頁打開時在本地運行。們能夠直接嵌入到網頁或者其餘特定的容器中,並可以產生特殊的效果。
全部基於Java的服務器端編程都是構建在Servlet之上的。在J2EE中Servlet已是一個標準的組件。
目前,Servlet引擎通常是第三方的插件,它經過必定的方法鏈接到Web服務器,Servlet引擎把它識別爲Servlet請求的那些HTTP請求截獲下來處理,而其餘的HTTP請求由Web服務器按照一般的方式來處理,Servlet引擎會裝載合適的Servlet到內存中,若是Servlet尚未運行的話,會分配一個可使用的線程來處理請求,再把Servlet的輸出返回到發出請求的Web客戶機。
Java Servlet和Java Applet正好是相對應的兩種程序類型,Applet運行在客戶端,在瀏覽器內執行,而Servlet在服務器內部運行,經過客戶端提交的請求啓動運行。
一樣的Servlet徹底能夠在Apache,IIS等不一樣Web服務器上執行,無論底層的操做系統是Windows,Solaris,Mac,Linux。
Java Servlet有着十分普遍的應用。使用Servlet還能夠實現大量的服務器端的管理維護功能,以及各類特殊的任務,好比,併發處理多個請求,轉送請求,代理等。
典型的Servlet運行環境有JSWDK,Tomcat,Resin等,。它們都自帶一個簡單的HTTP Server,只需簡單配置便可投入使用,你也能夠把它們綁定到經常使用的Web服務器上,如Apache,IIS等,提供小規模的Web服務。還有一些商業的大中型的支持Servlet和JSP的Web服務器,如JRun,Web Sphere,Web Logic等等,配置比較複雜,並不適合初學者。可是功能較爲強大,有條件的讀者能夠一試。
在使用這些方法時必須帶兩個參數。第一個包含來自客戶端的數據HttpServletRequest。第二個參數包含客戶端的相應HttpServletResponse。
一個HttpServletRequest對象提供請求HTTP頭部數據,也容許獲取客戶端的數據。怎樣獲取這些數據取決於HTTP請求方法。無論何種HTTP方式,均可以用getParameterValues方法返回特定名稱的參數值。HttpServletRequest,HttpServletResponse接口分別繼承於ServletRequest和ServletResponse接口,getParameterValues和getWriter方法都是其祖先接口中的方法。
對於HTTP GET請求的方式,getQueryString方法將會返回一個能夠用來解剖分析的參數值。
對於用HTTP POST,PUT和DELETE請求的方式,HttpServletRequest有兩種方法能夠選擇:若是是文本數據,你能經過getReader的方法獲得BufferedReader獲取數據;若是是二進制數據,能夠經過getInputStream方法獲得ServletInputStream獲取數據。
爲了相應客戶端,一個HttpServletResponse對象提供返回數據給用戶的兩個方法:一種是用getWriter方法獲得一個PrintWriter,用於返回文本數據;另外一種方法是用getOutputStream方法獲得ServletOutputStream,用於返回二進制數據。在使用Writer或OutputStream以前應先設置頭部(HttpServletResponse中有相應的方法),而後用Writer或OutputStream將相應的主體部分發給用戶。完成後要關閉Writer或OutputStream以便讓服務器知道相應已經結束。
在進行HTTP網絡傳輸的時候,統一採用的編碼方式是ISO-8859-1
字符編碼轉換經常使用的方法是
String native_encoded = "中文字符串"; //本地編碼的字符串
Byte[] byte_array = native_encoded.getBytes(); //獲得本地編碼的字節數組
String net_encoded = new String(native_encoded, "ISO-8859-1"); //生成ISO-8859-1編碼的字符串
例:out.println(new String(new String("<td>你的姓名:</td>").getBytes(),"ISO-8859-1"));
用Servlet控制會話
會話狀態的維持是開發Web應用所必須面對的問題,有多種方法能夠來解決這個問題,如使用Cookies,或直接把狀態信息加到URL中等,還有Servlet自己提供了一個HttpSession接口來支持會話狀態的維持 。
Session的發明是爲了填補HTTP協議的侷限。
從服務器這端來看,每個請求都是獨立的,所以HTTP協議被認爲是無狀態協議,當用戶在多個主頁間切換時,服務器沒法知道他的身份。Session的出現就是爲了彌補這個侷限。利用Session,您就能夠當一個用戶在多個主頁間切換的時候也能保存他的信息。這樣不少之前根本沒法去作的事情就變得簡單多了。
在訪問者從到達某個特定的主頁到離開爲止的那段時間,每一個訪問者都會單獨得到一個Session
Java Servlet定義了一個HttpSession接口,實現的Session的功能,在Servlet中使用Session的過程以下:
(1) 使用HttpServletRequest的getSession方法獲得當前存在的session,若是當前沒有定義session,則建立一個新的session,還可使用方法getSession(true)
(2) 寫session變量。可使用方法HttpSession.setAttribute(name,value)來向Session中存儲一個信息。
(3) 讀Session變量。可使用方法HttpSession.getAttribute(name)來讀取Session中的一個變量值,若是name是一個沒有定義的變量,那麼返回的是null。須要注意的是,從getAttribute讀出的變量類型是Object,必須使用強制類型轉換,好比:String uid = (String) session.getAttribute("uid");
(4) 關閉session,當時用完session後,可使用session.invalidate()方法關閉session。可是這並非嚴格要求的。由於,Servlet引擎在一段時間以後,自動關閉seesion。
HttpSession session = request.getSession(true); //參數true是指在沒有session時建立一個新的
Date created = new Date(session.getCreationTime()); //獲得session對象建立的時間
out.println("ID " + session.getId()+"<br>"); //獲得該session的id,並打印
out.println("Created: " + created+"<br>");//打印session建立時間
session.setAttribute("UID","12345678"); //在session中添加變量UID=12345678
session.setAttribute("Name","Tom"); //在session中添加變量Name=Tom 10.2.4 Servlet的生命週期
跟客戶端的Applet類似,Servlet也遵循嚴格的生命週期。在每一個Servlet實例的生命中有三種類型的事件,這三種事件分別對應於由Servlet引擎所喚醒的三個方法:
1.init()。當Servlet第一次被裝載時,Servlet引擎調用這個Servlet的init()方法,只調用一次。系統保證,在init方法成功完成之前,是不會調用Servlet去處理任何請求的。
2.service()。這是Servlet最重要的方法,是真正處理請求的地方。對於每一個請求,Servlet引擎將調用Servlet的service方法,並把Servlet請求對象和Servlet響應對象做爲參數傳遞給它。
3.destroy()。這是相對於init的可選方法,當Servlet即將被卸載時由Servlet引擎來調用,這個方法用來清除並釋放在init方法中所分配的資源。
Servlet的生命週期能夠被概括爲如下幾步:
(1) 裝載Servlet,這一項操做通常是動態執行的。然而,Servlet一般會提供一個管理的選項,用於在Servlet啓動時強制裝載和初始化特定的Servlet
(2) Server建立一個Servlet實例
(3) Server調用Servlet的init方法
(4) 一個客戶端請求到達Server
(5) Server建立一個請求對象
(6) Server建立一個響應對象
(7) Server激活Servlet的service方法,傳遞請求和響應對象做爲參數
(8) service方法得到關於請求對象的信息,處理請求,訪問其餘資源,得到須要的信息
(9) service方法使用響應對象的方法。將響應傳回Server,最終到達客戶端。Service方法可能激活其餘方法以處理請求。如doGet,doPost或其餘程序員本身開發的方法
(10) 對於更多的客戶端請求,Server建立新的請求和響應對象,仍然激活此servlet的service方法,將這兩個對象做爲參數傳遞給它,如此重複以上的循環,但無需再次調用init方法,Servlet通常只初始化一次
(11) 當Server再也不須要Servlet時,好比當Server要關閉時,Server調用Servlet的destroy
JSP通常的運行方式爲:當服務器啓動後,當Web瀏覽器端發送過來一個頁面請求時,Web服務器先判斷是不是JSP頁面請求。若是該頁面只是通常的HTML/XML頁面請求,則直接將HTML/XML頁面代碼傳給Web瀏覽器端。若是請求的頁面是JSP頁面,則由JSP引擎檢查該JSP頁面,若是該頁面是第一次被請求、或不是第一次被請求但已被修改,則JSP引擎將此JSP頁面代碼轉換成Servlet代碼,而後JSP引擎調用服務器端的Java編譯器javac.exe對Servlet代碼進行編譯,把它變成字節碼(.class)文件,而後再調用JAVA虛擬機執行該字節碼文件,而後將執行結果傳給Web瀏覽器端。若是該JSP頁面不是第一次被請求,且沒有被修改過,則直接由JSP引擎調用JAVA虛擬機執行已編譯過的字節碼.class文件,而後將結果傳送Web瀏覽器端。
採用JSP來表現頁面,採用Servlet來完成大量的處理,Servlet扮演一個控制者的角色,並負責響應客戶請求。Servlet建立JSP須要的Bean和對象,根據用戶的行爲,決定將哪一個JSP頁面發送給用戶。特別要注意的是,JSP頁面中沒有任何商業處理邏輯,它只是簡單的檢索Servlet先前建立的Beans或者對象,再將動態內容插入預約義的模板。