JSP與Servlet

原帖沒找到,只能轉載別人轉載的,轉載自:http://blog.csdn.net/floating520/article/details/7304005

JSP與Servlet
這篇文章的主要目的不是單純的介紹JSP,也不是詳細的介紹Servlet。這是一篇講述JSP和Servlet之間關係的基礎性文章。這篇文章主要是針對那些學習JSP的人而寫的。至於Servlet和JavaBean以及Servlet和XML我的兩個同學在他們的文檔中將會給出明確的解釋。
本文的主要結構:
1. Servlet是什麼?
2. JSP與Servlet.
3. Servlet 概述
4. 附錄一
5. 附錄二
在講述的過程中,主要是針對JSP和Servlet關係區別來寫。
而本文的內容順序之所以按這種方式來寫是爲了體現技術的發展順序。
附錄一提供了有關怎樣來運行一個Servlet的內容,完全是按本人的經驗來寫,其內容已經經過本人的證實。
附錄二中收集了一些純粹的實踐筆記。(轉載)
一. Servlet是什麼?
客戶機/服務器計算的發展。Java提供了一整套客戶機/服務器解決方案,在這個方案中,程序可以自動地下載到客戶端並執行,這就是applet。但是它僅僅是問題的一半。問題的另一半就是Servlet。
servlet可以被認爲是服務器端的applet。servlet被Web服務器加載和執行,就如同applet被瀏覽器加載和執行一樣。servlet從客戶端(通過Web服務器)接收請求,執行某種作業,然後返回結果。使用servlet的基本流程如下:
·客戶端通過HTTP提出請求.
·Web服務器接收該請求並將其發給servlet。如果這個servlet尚未被加載,Web服務器將把它加載到Java虛擬機並且執行它。
·servlet將接收該HTTP請求並執行某種處理。
·servlet將向Web服務器返回應答。
·Web服務器將從servlet收到的應答發送給客戶端。
由於servlet是在服務器上執行,通常與applet相關的安全性的問題並不需實現。要注意的是Web瀏覽器並不直接和servlet通信,servlet是由Web服務器加載和執行的。
而servlet是用Java編寫的,所以它們一開始就是平臺無關的。這樣,Java編寫一次就可以在任何平臺運行(write once,run anywhere)的承諾就同樣可以在服務器上實現了。servlet還有一些CGI腳本所不具備的獨特優點: (本人對CGI並不是十分了解,所以這些特點不能完全的體會到,這也是摘自論壇的貼子,請見諒)
servlet是持久的。servlet只需Web服務器加載一次,而且可以在不同請求之間保持服務(例如一次數據庫連接)。與之相反,CGI腳本是短暫的、瞬態的。每一次對CGI腳本的請求,都會使Web服務器加載並執行該腳本。一旦這個CGI腳本運行結束,它就會被從內存中清除,然後將結果返回到客戶端。CGI腳本的每一次使用,都會造成程序初始化過程(例如連接數據庫)的重複執行。
servlet是與平臺無關的。如前所述,servlet是用Java編寫的,它自然也繼承了Java的平臺無關性。
servlet是可擴展的。由於servlet是用Java編寫的,它就具備了Java所能帶來的所有優點。Java是健壯的、面向對象的編程語言,它很容易擴展以適應你的需求。servlet自然也具備了這些特徵。
servlet是安全的。從外界調用一個servlet的惟一方法就是通過Web服務器。這提供了高水平的安全性保障,尤其是在你的Web服務器有防火牆保護的時候。
   setvlet可以在多種多樣的客戶機上使用。由於servlet是用Java編寫的,所以你可以很方便地在HTML中使用它們,就像你使用applet一樣。
那麼,Servlet是怎樣執行的?怎樣來寫一個Servlet,它的基本架構是怎麼樣的?
這些問題,將在後面部分給予介紹。
二.JSP與Servlet
現在已經對Servlet有了大概的瞭解,現在我們就來說說JSP和Servlet的關係。
JSP是一種腳本語言,包裝了Java Servlet系統的界面,簡化了Java和Servlet的使用難度,同時通過擴展JSP標籤(TAG)提供了網頁動態執行的能力。儘管如此,JSP仍沒有超出Java和Servlet的範圍,不僅JSP頁面上可以直接寫Java代碼,而且JSP是先被譯成Servlet之後才實際運行的。JSP在服務器上執行,並將執行結果輸出到客戶端瀏覽器,我們可以說基本上與瀏覽器無關。它是與JavaScript不同的,JavaScript是在客戶端的腳本語言,在客戶端執行,與服務器無關。

那麼JSP是什麼?就是Servlet.
JSP與Servlet之間的主要差異在於,JSP提供了一套簡單的標籤,和HTML融合的比較好,可以使不瞭解Servlet的人可以做出動態網頁來。對於Java語言不熟悉的人(比如像我),會覺得JSP開發比較方便。JSP修改後可以立即看到結果,不需要手工編譯,JSP引擎會來做這些工作;而Servelt缺需要編譯,重新啓動Servlet引擎等一系列動作。但是在JSP中,HTML與程序代碼混雜在一起,而Servlet卻不是這樣。也許大家比較混亂了,那麼Servlet又是什麼?下面我們對JSP的運行來做一個簡單的介紹,告訴大家怎樣來執行一個JSP文件:
當Web服務器(或Servlet引擎,應用服務器)支持JSP引擎時,JSP引擎會照着JSP的語法,將JSP文件轉換成Servlet代碼源文件,接着Servlet會被編譯成Java可執行字節碼(bytecode),並以一般的Servlet方式載入執行
JSP語法簡單,可以方便的嵌入HTML之中,很容易加入動態的部分,方便的輸出HTML。在Servlet中輸出HTML缺需要調用特定的方法,對於引號之類的字符也要做特殊的處理,加在複雜的HTML頁面中作爲動態部分,比起JSP來說是比較困難的。
除去了轉換和編譯階段,JSP和Servlet之間的區別實在是不大。
JSP引擎通常架構在Servlet引擎之上,本身就是一個Servlet,把JSP文件轉譯成Servlet源代碼,再調用Java編譯器,編譯成Servlet。這也是JSP在第一次調用時速度比較慢的原因,在第一次編譯之後,JSP與Servlet速度相同.下面我們來看看爲什麼他們在第一次編譯後再編譯的速度相同:
在整個運行過程中,JSP引擎會檢查編譯好的JSP(以Servlet形式存在)是否比原始的JSP文件還新,如果是,JSP引擎不會編譯;如果不是,表示JSP文件比較新,就會重新執行轉譯與編譯的過程。
爲了有個深刻的瞭解,我們看一下JSP的運行和開發環境:
瀏覽器:常見的瀏覽器有IE和Netscape兩種。
數據庫:常用的數據庫有Oracle,SQL Server,Informix,DB2,Sybase,Access,MySQL等。
操作系統:常見的有Windows,Linux,以及各種Unix系統。
Web服務器:常見的有IIS,Apache,Netscape Enterprise Server等。
JSP引擎:一般JSP引擎都以Servlet引擎爲基礎,並以Servlet的形式出現。同時,在各種免費和商業引擎的實現中,Servlet引擎和Jsp引擎通常也是一起出現,我們成爲Servlet/JSP引擎,或從某種成爲JSP引擎。
JSP引擎是可以提供JSP和Servlet運行支持並對其生存週期進行管理的系統級實體。
在JSP頁面第一次被請求時,JSP引擎會將JSP原始文件轉換成Servlet源代碼,然後調用Java編譯器,編譯成Servlet,並在Servlet引擎中執行。當再次有請求的時候,JSP引擎會見差異編譯好的JSP是否比原來的JSP原始文件要新,如果是,運行Servlet;如果不是,表示文件已經更新的了,就會從新執行轉換和編譯的過程。
說到這裏,也基本把JSP和Servlet的關係說清楚了,從我的感覺上看用JSP就可以了,簡單又方便,又可以和Bean 很好的兼容使用,功能又很強大,爲什麼又出現了Servlet,它又有什麼用?何況它的編寫又相對複雜。爲了把問題說得更清楚一點,我想在這裏說一下歷史,順便再講一下爲什麼還要用Servlet,Servlet的好處是什麼。
歷史簡述:(摘自某論壇有刪節,改寫)
簡單的說,SUN首先發展出SERVLET,其功能比較強勁,體系設計也很先進,只是,它輸出HTML語句還是採用了老的CGI方式,是一句一句輸出,所以,編寫和修改HTML非常不方便。
後來SUN推出了類似於ASP的鑲嵌型的JSP(是Servlet發展的產物),把JSP TAG鑲嵌到HTML語句中,這樣,就大大簡化和方便了網頁的設計和修改。新型的網絡語言如ASP,PHP,JSP都是鑲嵌型的SCRIPT語言。
從網絡三層結構的角度看,一個網絡項目最少分三層:data layer,business layer, presentation layer。當然也可以更復雜。SERVLET用來寫business layer是很強大的,但是對於寫presentation layer就很不方便。JSP則主要是爲了方便寫presentation layer而設計的。當然也可以寫business layer。寫慣了ASP,PHP,CGI的朋友,經常會不自覺的把presentation layer和business layer混在一起。把數據庫處理信息放到JSP中,其實,它應該放在business layer中。 
根據SUN自己的推薦,JSP中應該僅僅存放與presentation layer有關的內容,也就是說,只放輸出HTML網頁的部份。而所有的數據計算,數據分析,數據庫聯結處理,統統是屬於business layer,應該放在JAVA BEANS中。通過JSP調用JAVA BEANS,實現兩層的整合。 
實際上,微軟推出的DNA技術,簡單說,就是ASP+COM/DCOM技術。與JSP+BEANS完全類似,所有的presentation layer由ASP完成,所有的business layer由COM/DCOM完成。通過調用,實現整合。現在微軟推出的.NET也是通過這個理念,所有的presentation layer由ASP.NET完成,business layer由C#或VB.NET或VC.NET來完成。
爲什麼要採用這些組件技術呢?因爲單純的ASP/JSP語言是非常低效率執行的,如果出現大量用戶點擊,純SCRIPT語言很快就到達了他的功能上限,而組件技術就能大幅度提高功能上限,加快執行速度。 
另外一方面,純SCRIPT語言將presentation layer和business layer混在一起,造成修改不方便,並且代碼不能重複利用。如果想修改一個地方,經常會牽涉到十幾頁CODE,採用組件技術就只改組件就可以了。 
綜上所述,SERVLET是一個早期的不完善的產品,寫business layer很好,寫presentation layer就很不好,並且兩層混雜,顯得十分混亂。
所以,推出JSP+BAEN,用JSP寫presentation layer,用BAEN寫business layer。SUN自己的意思也是將來用JSP替代SERVLET。
看了上面的敘述,大家可能對JSP與Servlet共存有了比較好的認識。可以看到JSP和Bean結合後的的實用性,強大的表現功能,易用性都是Servlet所不能及的。那麼是不是Servlet就被取代了?不是!在以後的發展中,它還是有着巨大的作用的。上面只不過是將了問題的一方面,下面我們來看看Servlet本身的特點。
由於它是由java來寫的,所以相關的特點我們就不說了,上文已經有了詳細的介紹,我們來看看其他的:
Servlet是用於開發服務器端應用程序的一種編程模型,如果只是一個普通的java應用,可以不使用servlet來編寫,但是如果想要提供基於web的服務能力,那麼就必須按照這種模型來編寫,而且servlet也必須允許在符合servlet規範的java web server or app server之上,否則無法運行。除非你自己實現一個web server,但是其複雜度是比較高的,特別是在企業級應用中,對系統的穩定性和健壯性都要求比較高,所以servlet的模型實際上是簡化了編寫穩健的服務器端的應用開發過程。Servlet 可以作爲提供web服務能力的一個接入方式
現在也許可以理解了什麼是Servlet什麼是JSP,它們之間的關係是怎樣的。下面我就對Servlet這個技術做一個簡要的介紹。
Servlet概述
一.Servlet的結構
在Servlet API中最重要的是Servlet interface. 所有的servlets implement(執行)這個interface, 方式多種:或者是直接的,或者通過extending 這個class執行它,如 HttpServlet. 這個Servlet interface 提供安排servlet與客戶端聯繫的方法. Servlet 編寫者可以在他們開發servlet程序時提供更多一些或所有的這樣方法. 
當一個servlet接收來自客戶端的調用請求, 它接收兩個對象: 一個是ServletRequest,另外一個是ServletResponse. 這個ServletRequest class 概括從客戶端到服務器之間的聯繫, 而 ServletResponse class 概括從servlet返回客戶端的聯繫. 
ServletRequest interface 可以獲取到這樣一些信息如由客戶端傳送的闡述名稱,客戶端正在使用的協議, 產生請求並且接收請求的服務器遠端主機名. 它也提供獲取數據流的servlet, ServletInputStream, 這些數據是客戶端引用中使用HTTP POST 和 PUT 方法遞交的. 一個ServletRequest的子類可以讓servlet獲取更多的協議特性數據. 例如: HttpServletRequest 包含獲取HTTP-specific頭部信息的方法. 
ServletResponse interface 給出相應客戶端的servlet方法. 它允許servlet設置內容長度和迴應的mime類型, 並且提供輸出流, ServletOutputStream, 通過編寫者可以發回相應數據. ServletResponse子類可以給出更多protocol-specific容量的信息。 例如: HttpServletResponse 包含允許servlet操作HTTP-specific頭部信息的方法. 
上面有關classes 和 interfaces描述構成了一個基本的Servlet框架. HTTP servlets有一些附加的可以提供session-tracking capabilities的方法. servlet編寫者可以用這些API在有他人操作時維護servlet與客戶端之間的狀態.
二.編寫Servlet
Servlets 執行 javax.servlet.Servlet interface. servlet編寫者可以通過直接implement interface開發servlet, 但這樣通常沒有必要. 因爲大多數servlet是針對用HTTP協議的web服務器, 這樣最通用開發servlet辦法是用 javax.servlet.http.HttpServlet 內.HttpServlet 類通過extend GenericServlet基類執行 Servlet interface, 提供了處理HTTP協議的功能. 他的service方法支持標準HTTP/1.1請求. 一般地, 用HttpServlet指定的類編寫的servlets可以多線程地併發運行service方法.
Servlet編寫者注意HttpServlet類有幾個欠缺的方法,你可以自己定義方法中內容,但是必須使用這些方法名稱以使servlet知道你想做什麼, 
doGet, 用於處理 GET、有條件的GET 和頭部 HEAD請求 
doPost, 用戶處理 POST 請求
doPut, 用於處理 PUT 請求
doDelete, 用於處理 DELETE請求 
HttpServlet的service方法, 一般地, 當它接收到一個OPTIONS請求時,會調用doOptions 方法, 當接收一個TRACE請求是調用doTrace . doOptions缺省執行方式是自動決定什麼樣的HTTP被選擇並且返回哪個信息. 
在你使用這些方法時,必須帶兩個闡述. 第一個包含來自客戶端的數據HttpServletRequest. 第二個參數包含客戶端的響應HttpServletResponse. 在下例中是這樣的情況. 
一個HttpServletRequest對象提供到達HTTP 頭部數據, 也允許你獲取客戶端的數據. 怎樣獲取這些數據取決於HTTP端請求方法. 
不管任何HTTP方式, 你可以用]getParameterValues方法, 這個用來返回特定名稱的參數值.
對於用 HTTP GET 請求的方式, 這個getQueryString方法將會返回一個可以用來解剖分析的。對於用HTTP POST, PUT, 和 DELETE請求的方式, 你有兩種方法可以選擇. 如果是文本數據,你能通過getReader方法用BufferedReader獲取;如果是二進制數據, 能通過getReader 方法用 ServletInputStream獲取.
爲了響應客戶端, 一個HttpServletResponse對象提供返回數據給用戶的兩個方法. 你可以用getWriter 方法返回,或者 getOutputStream 方法以輸出流返回. 你應該用getWriter返回文本數據,而用getOutputStream返回二進制數據. 
在使用Writer 或 OutputStream之前, HTTP 頭部應該先被設置. HttpServletResponse內提供這樣一個方法,之後可以用writer 或 outputstream 將響應主體部分發回用戶. 完成後要關閉 writer 或 output stream以便讓服務器知道響應已經完畢. 


附錄一
運行你的Servlet!
當一個servlet已經寫好怎樣來運行測試呢?我花了好長時間來研究這個,也許是因爲我太笨。但其實現在想想也不是很難。我想通過一個例子詳細的說說,這樣會有一個感性的把握。我會把我當時遇到的主要問題用黑體字寫出,那時我當時主要浪費時間的地方,希望大家也注意。(我用的運行環境是Tomcat5.0)
首先我們來寫一個最簡單的servlet:
package test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloServlet extends HttpServlet{
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");

PrintWriter out=response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("<p>Hello!這是我的第一個Java Servlet程序。</p>");
out.println("</BODY>");
out.println("</HTML>");
}
}
由於我們把它進行了打包,所以把這個編譯好的.class文件放到\Tomcat文件夾\webapps\ourappfiles\WEB-INF\classes\test的文件夾下。
接着我們需要寫一個調用該Servlet的html文件:
<html>
<head>
<title>Java Servlets Sample-Properties</title>
</head>
<body>
<form method="get" action="test.HelloServlet">
<input name="test" type="submit" value="Test HelloServlet servlet">
</body>
</html>
注意:這裏的method不能用post,不然不會在IE中正常顯示,我當初就是在這個地方沒有弄好,浪費了好多時間。至於爲什麼這樣寫,我也弄不太清楚,由於水平有限,多多包涵。
現在我們還差最後一步,編寫我們的web.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>helloservlet</servlet-name>
<servlet-class>test.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloservlet</servlet-name>
<url-pattern>/test.HelloServlet</url-pattern>
</servlet-mapping>
</web-app>
把編寫好的web.xml文件放到\Tomcat文件夾\webapps\ourappfiles\WEB-INF下。
好了,現在萬事俱備,就差啓動Tomcat運行我們的Servlet了。
以上就是運行Servlet的幾個步驟。
附錄二
這個附錄純粹是另一個讀書筆記,我感覺比較好,所以摘錄下來。裏面寫的是經驗的結晶,我還沒有這麼多的經驗,所以只有摘抄別人的以作補充了。
1.ServletConfig
l 一個ServletConfig對象是servlet container在servlet initialization的時候傳遞給servlet的。

ServletConfig包涵 ServletContext 和 一些 Name/Value pair (來自於deployment descriptor)

l ServletContext接口封裝了Web應用程序的上下文概念。

2.會話跟蹤
1) Session
l 當一個Client請求多個Servlets時,一個session可以被多個servlet共享。

l 通常情況下,如果server detect到browser支持cookie,那麼URL就不會重寫。


2) cookie
l 在Java Servlet中,如果你光 Cookie cookie = new Cookie(name,value)
那麼當用戶退出Browser時,cookie會被刪除掉,而不會被存儲在客戶端的硬盤上。

如果要存儲 cookie,需加一句 cookie.setMaxAge(200)

l cookie是跟某一個server相關的,運行在同一個server上的servlet共享一個cookie.

3) URL Rewriting
在使用URL Rewriting來維護Session ID的時候,每一次HTTP請求都需要EncodeURL()
典型的用在兩個地方
1) out.print(“form action=\” ”);
out.print(response.encodeURL(“sessionExample”));
out.print(“form action=\” ”);
out.print(“method = GET>”);
2) out.print(“<p><a href=\” ”);
out.print(response.encodeURL(“SessionExample?database=foo&datavalue=bar”));
out.println(“\” >URL encoded </a>”);

3.SingleThreadModel
默認的,每一個servlet definition in a container只有一個servlet class的實例。
只有實現了SingleThreadModel,container纔會讓servlet有多個實例。

Servlet specification上建議,不要使用synchronized,而使用SingleThreadModel。

SingleThreadModel(沒有方法)
保證servlet在同一時刻只處理一個客戶的請求。
SingleThreadModel是耗費資源的,特別是當有大量的請求發送給Servlet時,SingleThreadModel的作用是使包容器以同步時鐘的方式調用service方法。
這等同於在servlet的service()方法種使用synchronized.

Single Thread Model一般使用在需要響應一個heavy request的時候,比如是一個需要和數據庫打交道的連接。


2. 在重載Servlet地init( )方法後,一定要記得調用super.init( );

3. the client通過發送一個blank line表示它已經結束request
而the server通過關閉the socket來表示response已結束了。

4. 一個Http Servlet可以送三種東西給Client
1) a single status code
2) any number of http headers
3) a response body

5. Servlet之間信息共享的一個最簡單的方法就是
System.getProperties().put(“key”,”value”);

6. Post和Get
Post:將form內各字段名稱和內容放置在html header內傳送給server
Get: ?之後的查詢字符串要使用URLEncode,經過URLEncode後,這個字符串不再帶有空格,以後將在server上恢復所帶有的空格。

Get是Web上最經常使用的一種請求方法,每個超鏈接都使用這種方法。

7. Web.xml就是Web Applicatin 的deployment descriptor
作用有:組織各類元素
設置init param
設置安全性

8. Request Dispatcher用來把接收到的request forward processing到另一個servlet
要在一個response裏包含另一個servlet的output時,也要用到Request Dispatcher.

9. Servlet和Jsp在同一個JVM中,可以通過ServeltContext的
setAttribute( )
getAttribute( )
removeAttribute( )
來共享對象
10. 利用request.getParameter( )得到的String存在字符集問題。
可以用 strTitle = request.getParameter(“title”);
strTitle = new String(strTitle.getBytes(“8859-1”),”gb2312”);

如果你希望得到更大得兼容性
String encoding = response.getCharacterEncoding(); //確定Application server用什麼編碼來讀取輸入的。
strTitle = new String(strTitle.getBytes(encoding),”gb2312”);

發佈了23 篇原創文章 · 獲贊 7 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章