Servlet入門1
1.1 關於Servlets
Servlets是JAVA 2.0中新增的一個全新功能。JAVA Servlets 是運行在請求/面向請求服務器上的模塊,好比一個Java-enabled web 服務器, 和相似這樣的延伸場合. 例如, 一個servlet能夠從一個HTML訂單表中獲取數據而後用一些商業上的算法來更新公司相應的訂單數據庫。
也就是說:servlet可以象CGI腳本同樣擴展WEB服務器功能,可是servlet佔用不多密集資源,有不少用CGI腳本編制的一些站點由 於訪問量劇增,性能迅速降低,這是CGI腳本一個缺點。同時因爲servlet 是用java編寫的,所以是跨平臺的。實際servlet是電子商務真正的開始。
Servlet API, 是用來寫servlet的, 編寫servlet是已沒有CGI腳本那樣諸如關心一個servlet是這樣被裝載, servlet運行的服務器環境是什麼, 或者用來傳輸數據的協議是什麼等等,這樣servlets就能夠融合在不一樣的web服務器中.
Servlet能夠至關有效地替代CGI腳本: 它能夠方便地產生容易編寫並且運行快的動態文本. 能夠很方便的調試尋找出程序問題. Servlet程序是用Java Servlet API開發的, a standard Java extension. 但不是Java 核心框架的一部分,能夠做爲通用的附加產品包被商家購買使用.
1.2 舉例
下面是一些servlet應用範圍:
用於處理HTML表單經過HTTPS產生POSTed數據, 包括買賣訂單或信用卡數據. 所以servlet能夠成爲訂單處理系統的一部分, 和產品存貨數據庫一道工做,也許能夠用在在線支付系統上.
容許人們之間的合做. 一個servlet能併發處理多個請求; 他們可使用在諸如在線會議這樣的同步請求支持系統.
轉送請求. Servlet能夠轉送請求給其餘的服務器和servlets. 這就容許在鏡象一樣內容的幾個服務器之間平衡負載. 按照任務類型或組織範圍,能夠容許被用來在幾個服務器中劃分邏輯上的服務器.
servlet 編寫者們能夠定義彼此之間共同工做的激活代理,每一個代理者是一個servlet, 並且代理者可以在他們之間傳送數據.
1.3 Servlet 結構總視
在具體掌握servlet以前,須對java語言有所瞭解。下面是基於您瞭解java基礎上的,在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與客戶端之間的狀態.
1.4 Servlet Lifecycle
服務器裝載運行servlets:接收來自客戶端的多個請求而且返回數據給客戶端. 而後在刪除移開servlets. 這就是servlets lifecycle過程. 下面詳細描述:
當一個服務器裝載servlet時, 它運行servlet的 init 方法. 這個方法不能反覆調用,一旦調用就是再裝載servlet. 直到服務器調用 destroy 方法卸載 servlet後才能再調用.
在服務器裝載初始化後servlet, servlet就可以處理客戶端的請求. 用 service 方法作到這一點. 每一個客戶端請求有它本身service方法: 這些方法接收客戶端請求, 而且發回相應的響應.
Servlets能同時運行多個service. 這是很重要的, 這樣, service方法能夠按一個thread-safe 樣式編寫. 如:service方法更新servlet對象中的一個字段field, 這個字段能夠同時存取的. 假如某個服務器不能同時併發運行 service方法,也能夠用SingleThreadModel interface. 這個 interface 保證不會有兩個以上的線程threads併發運行.
Servlets一直運行到他們被服務器卸載。
在servlet的lifecycle中, 編寫一個thread-safe編碼以卸載servlet是很重要的。html
Servlet入門外2
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方法.
2.1 與客戶端的交互性
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以便讓服務器知道響應已經完畢.
2.2 一個HTTP Servlet處理GET和HEAD方法的例子
public class SimpleServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
// 首先設置頭部
res.setContentType("text/html");
// 用 writer方法返回響應數據
PrintWriter out = res.getWriter();
out.println("<HEAD><TITLE> SimpleServlet Output</TITLE></HEAD><BODY>");
out.println("<h1> SimpleServlet Output </h1>");
out.println("<P>This is output is from SimpleServlet.");
out.println("</BODY>");
out.close();
}
public String getServletInfo() {
return "A simple servlet";
}
}
這個例子完整地現實了一個servlet.
2.3 一個HTTP Servlet處理POST方式的例子
這裏是個用HTML帶POST表單的例子:
<html>
<head><title>JdcSurvey</title></head>
<body>
<form action=http://demo:8080/servlet/survey method=POST>
<input type=hidden name=survey value=Survey01Results>
<BR><BR>How Many Employees in your Company?<BR>
<BR>1-100<input type=radio name=employee value=1-100>
<BR>100-200<input type=radio name=employee value=100-200>
<BR>200-300<input type=radio name=employee value=200-300>
<BR>300-400<input type=radio name=employee value=300-400>
<BR>500-more<input type=radio name=employee value=500-more>
<BR><BR>General Comments?<BR>
<BR><input type=text name=comment>
<BR><BR>What IDEs do you use?<BR>
<BR>JavaWorkShop<input type=checkbox name=ide value=JavaWorkShop>
<BR>J++<input type=checkbox name=ide value=J++>
<BR>Cafe'<input type=checkbox name=ide value=Cafe'>
<BR><BR><input type=submit><input type=reset>
</form>
</body>
</html>
這裏的servlet將表單數據寫入一個文件,而且用一個thank you信息響應用戶. 這裏servlet的方法,以下例:
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
// 首先設置響應的 "content type" 頭部
res.setContentType("text/html");
//獲得響應的 PrintWriter以返回文本給客戶端.
PrintWriter toClient = res.getWriter();
try {
//打開一個文件寫入Survey的結果.
String surveyName = req.getParameterValues("survey")[0];
FileWriter resultsFile = new FileWriter(resultsDir
+ System.getProperty("file.separator")
+ surveyName + ".txt", true);
PrintWriter toFile = new PrintWriter(resultsFile);
// 從客戶端獲得表單數據 & 存貯在這個文件中
toFile.println("");
Enumeration values = req.getParameterNames();
while(values.hasMoreElements()) {
String name = (String)values.nextElement();
String value = req.getParameterValues(name)[0];
if(name.compareTo("submit") != 0) {
toFile.println(name + ": " + value);
}
}
toFile.println("");
//關閉文件.
resultsFile.close();
// 用一個thank you返回客戶端
toClient.println("");
toClient.println("");
toClient.println("Thank you for participating");
toClient.println("");
} catch(IOException e) {
e.printStackTrace();
toClient.println(
"A problem occured while recording your answers. "
+ "Please try again.");
}
// 關閉writer; 響應完成.
toClient.close();
}
這個doPost方法是用getParameterNames和getParameterValues方法來從表單中獲取數據的. 由於它返回文本給客戶端, doPost 將調用 getWriter 方法. 在寫入響應主體部分以前,它設置了響應頭部字段的設置, 但響應完成後,關閉.java
Servlet入門3
Lifecycle 方法
3.1 重編Init 初始化方法
在初始化過程當中, servlet應當準備好它要安排的一些資源, 以便這個servlet 可以接收請求,作到這些能夠不用考慮多線程, 由於在servlet初始化是隻能是單進程的。 一旦初始化方法完成, servlet就能接收客戶端的請求。 固然若是初始化不能成功,這個方法會扔出throw UnavailableException解釋的.
初始化方法使用ServletConfig 對象做爲參數. 這個方法應該保存這個對象, 以便它能有方法getServletConfig返回. 最簡單的辦法是,搞出一個新類,他的初始化方法數調用super.init. 若是確實這樣作, 你就應當本身保存ServletConfig 對象, 而且本身重編getServletConfig 方法以便它能重新的位置獲得對象.
下面是個初始化方法的例子. 它是來自Survey Servlet的初始化方法, 從一個表單接收輸入而後存儲到文件中,爲了存儲survey信息, 它須要一個目錄. 它以初始化參數接收這個目錄.
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
//獲取目錄
resultsDir = getInitParameter("resultsDir");
//若是沒有目錄, 不處理客戶端
if (resultsDir == null) {
throw new UnavailableException (this,
"Not given a directory to write survey results!");
}
}
這裏的初始化方法調用super.init 方法來管理安排ServletConfig對象. 這個初始化方法也設置了一個字段: resultsDir, 做爲初始化參數提供的目錄名. 若是沒有目錄名被提供, 這個 servlet扔出一個不適用的解釋. 若是初始化 方法成功完成,servlet將能處理客戶端請求
初始化參數
初始化參數的規定是一個服務器方面的規定。若是初始化參數被規定, 均可以用一樣的方法獲得: 用 getInitParameter方法. 這個方法將參數名做爲本身的參數項.
3.2 重編Destroy 方法
當服務器卸載一個servlet, 它將調用servlet的destroy方法. 這個 destroy方法是與初始化方法相反,同時從內存中釋放servlet.
並非全部的調用了初始化init方法是也必須調用destroy方法.
對於大多數的servlets, 一些初始化的工做必須反作的. 如, 假設有一個servlet,它在初始化時打開一個數據庫鏈接,他的destroy 方法以下顯示:須要關閉這個鏈接的
/**
* 關閉數據庫鏈接
*/
public void destroy() {
try {
con.close();
} catch (SQLException e) {
while(e != null) {
log("SQLException: " + e.getSQLState() + '\t' +
e.getMessage() + '\t' +
e.getErrorCode() + '\t');
e = e.getNextException();
}
} catch (Exception e) {
e.printStackTrace();
}
}
關於一個Servlet中斷涉及的多線程
但一個服務器卸載一個servlet, 它會在全部的service已經完成後調用 destroy. 若是你的操做運行須要很長時間, 但destroy 被調用時還有線程在運行. 這個servlet編寫者有責任確保全部的線程都已經完成;
長時間運行響應客戶端請求的那些servlet應當保留當前有多少方法在運行的記錄. 他的 long-running 方法應當週期性地輪詢以確保他們可以繼續運行下去. 若是servlet被destroy方法調用, 那麼這個long-running 方法若是必要必須中止工做或清除.
舉例, 變量serviceCounter用來統計有多少service方法在運行, 變量 shuttingDown顯示這個servlet是否被destory. 每一個變量有它本身的獲取方法:
public ShutdownExample extends HttpServlet {
private int serviceCounter = 0;
private Boolean shuttingDown;
...
// serviceCounter
protected synchronized void enteringServiceMethod() {
serviceCounter++;
}
protected synchronized void leavingServiceMethod() {
serviceCounter--;
}
protected synchronized int numServices() {
return serviceCounter;
}
//shuttingDown
protected setShuttingDown(Boolean flag) {
shuttingDown = flag;
}
protected Boolean isShuttingDown() {
return shuttingDown;
}
}
這個service方法每次在它進入時要增長,而在它返回退出時要減小:
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
enteringServiceMethod();
try {
super.service(req, resp);
} finally {
leavingServiceMethod();
}
}
destroy方法應當檢查serviceCounter, 若是存在長時間方式運行的話, 設置變量shuttingDown . 這個變量將會讓那個正在處理請求的線程知道:該結束了,關閉吧! destroy 方法應當等待這幾個service 方法完成, 這樣就是一個清楚的關閉過程了.
public void destroy() {
/* 檢查是否有線程在運行,若是存在,告訴他們stop. */
if (numServices() > 0) {
setShuttingDown(true);
}
/* 等待他們stop. */
while(numService() > 0) {
try {
thisThread.sleep(interval);
} catch (InterruptedException e) {
}
}
}
long-running 方法如必要應當檢查這個變量,而且解釋他們的工做:
public void doPost(...) {
...
for(i = 0; ((i < lotsOfStuffToDo) && !isShuttingDown()); i++) {
try {
partOfLongRunningOperation(i);
} catch (InterruptedException e) {
}
}
}
3.3 提供關於Servlet的信息
/**
* This is a simple example of an HTTP Servlet. It responds to the GET
* and HEAD methods of the HTTP protocol.
*/
public class SimpleServlet extends HttpServlet {
...
public String getServletInfo() {
return "A simple servlet";
}
}web
註明:本文轉載自http://www.cnblogs.com/goody9807/archive/2007/06/13/782519.html#undefined。算法