J2EE基礎之Servlet
1、 什么是Servlet?
Servlet即Java服務小程序,是使用應用程序設計接口以及相關類和方法的Java程序。它可以作為一種插件,像Applet程序一樣嵌入到Web服務器中運行。Servlet主要用於處理和客戶之間的通信,當客戶端傳來一個HTTP請求時,通過調用Servlet方法來向客戶端發送一個響應。
Servlet的主要功能在於交互式地瀏覽和修改數據,收集來自網頁表單的用戶輸入,呈現來自數據庫的記錄,還可以生成動態的Web內容。狹義的Servlet是指Java語言實現的一個接口,廣義的Servlet是指任何實現了這個Servlet接口的類,一般情況下,人們將Servlet理解為后者。
2、 Servlet工作模式
Servlet工作模式是:首先,客戶端發送請求至服務器;然后,服務器啟動並調用Servlet,Servlet根據客戶端請求生成響應內容並將其傳給服務器;最后,服務器把響應返回客戶端,具體如圖一:
圖一:Servlet架構
Servlet執行以下主要任務:
(1)讀取客戶端(瀏覽器)發送的顯示數據,包括網頁上的HTML表單,或者來自applet或自定義的HTTP客戶端程序 表單;
(2)讀取客戶端(瀏覽器)發送的隱式的HTTP請求數據,包括Cookie等;
(3)處理數據並生成結果,這個過程可能需要訪問數據庫;
(4)發送顯式的數據到客戶端,數據格式包括文本文件(HTML或XML)、二進制文件(GIF圖像)、Excel文件等;
(5)發送隱式的HTTP響應到客戶端,包括告訴瀏覽器或其他客戶端杯返回的文檔類型(例如,HTML),設置Cookie和緩存參數等。
3、 Servlet的生命周期
Servlet運行於應用服務器上的Web容器中(一般使用Tomcat)。應用服務器中用於管理Java組件的部分被稱為容器。當Servlet被部署在應用服務器中以后,由容器控制Servlet的生命周期。Servelt在第一次請求的時候被加載和實例化。Servlet 一旦被加載和實例化,一般不會從容器中刪除,直至應用服務器關閉或重新啟動。所以第一次訪問Servlet所有時間要多於以后訪問Servlet所用的時間。
Servlet生命周期可被定義為從創建直到被銷毀的整個過程,具體如圖二:
圖二:Servlet生命周期
具體執行有以下五個步驟:
(1)加載Servlet類,創建該類的實例。每一個用戶請求都會產生一個新線程;
(2)Servlet通過調用init()方法進行初始化;
(3)Servlet調用service()方法來處理客戶端的請求;
(4)Servlet通過調用destory()方法終止(結束);
(5) 最后,Servlet由JVM的垃圾回收器進行垃圾回收。
4、 使用Servlet有關Cookie的實例
該實例是通過在表單中輸入的學生姓名、學號、選課信息保存到Cookie中,然后再通過另一個Servlet讀出來。具體步驟如下:
(1) 首先,在MyEclipse中(此處我用的是MyEclipse)新建一個Web Project,命名為MyServlet
(2)在MyServlet項目中,新建第一個Servlet,命名為SelectLesson,具有代碼如下:
package liu; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class SelectLesson extends HttpServlet { /** * Constructor of the object. */ public SelectLesson() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Cookie存取時用URLEncoder.encode進行編碼(PS:讀取時URLDecoder.decode進行解碼) Cookie Name = new Cookie("name",java.net.URLEncoder.encode(request. getParameter("name"),"UTF-8")); Cookie Number = new Cookie("number",java.net.URLEncoder.encode(request. getParameter("number"),"UTF-8")); String lessons = ""; String[] paramLessons=request.getParameterValues("lessons"); for(int i=0;i<paramLessons.length;i++) lessons+=paramLessons[i]+" "; Cookie Lessons = new Cookie("lessons",java.net.URLEncoder.encode( lessons,"UTF-8")); Name.setMaxAge(60*60*24); Number.setMaxAge(60*60*24); Lessons.setMaxAge(60*60*24); response.addCookie(Name); response.addCookie(Number); response.addCookie(Lessons); response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>信息已被寫入Cookie!</TITLE></HEAD>"); out.println(" <BODY bgcolor=\"#f0f0f0\">\n>"); out.println("<h2 align=\"center\">信息已被寫入Cookie!</h2>\n"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init(ServletConfig config) throws ServletException { // Put your code here super.init(config); } }
(3)然后,再次在該項目中新建第二個Servlet,命名為ReadCookies,具體代碼如下:
package liu;
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ReadCookies extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; /** * Constructor of the object. */ public ReadCookies() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Cookie cookie = null; Cookie[] cookies=null; cookies=request.getCookies(); response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>從Cookie讀出一下信息:</TITLE></HEAD>"); out.println(" <BODY bgcolor=\"#f0f0f0\">\n"); if(cookies != null){ for(int i=0;i<cookies.length;i++){
cookie = cookies[i];
String name = cookie.getName();
//讀取時URLDecoder.decode進行解碼(PS:Cookie存取時用URLEncoder.encode進行編碼)
out.print(name+": "+java.net.URLDecoder.decode(cookie.getValue(),"utf-8")+"<br/>");
} } else out.print("<h2>未找到Cookies</h2>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); } public void init(ServletConfig config) throws ServletException { // Put your code here super.init(config); } }
(4)在MyServlet項目中,新建一個html文件,命名為SelLesson具體代碼如下:
<!DOCTYPE html> <html> <head> <title>學生選課</title> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="this is my page"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> </head> <body> <form action="/MyServlet/liu/SelectLesson"method="POST"> 姓名:<input type="text" name="name"/><br/> 學號:<input type="text" name="number"/><br/> <input type="checkbox" name="lessons" value="數學"/>數學 <input type="checkbox" name="lessons" value="物理"/>物理 <input type="checkbox" name="lessons" value="化學"/>化學<br/> <input type="submit" value="提交"> </form> </body> </html>
(5)具體運行結果截圖
打開瀏覽器,輸入:http://localhost:8080/MyServlet/ (注意:其中要把SelLesson.html在web.xml中設置為項目的默認首頁),然后輸入姓名、學號,選擇相應課程
圖三:運行結果截圖1
點擊提交后如下:
圖四:運行結果截圖2
最后,在瀏覽器中打開一個新的頁面,輸入:http://localhost:8080/MyServlet/liu/ReadCookies,可以看到如下結果(其中課程結果出現了亂碼,當時我設置嘗試了GB2312和UTF-8,均是亂碼,亂碼問題還未得到解決,大神路過求指點(⊙o⊙)哦):
圖五:運行結果截圖3
本文亂碼原因:
Cookie在讀取時使用java.net.URLDecoder.decode進行解碼,Cookie存取時用java.net.URLEncoder.encode進行編碼。
但是我在實際存時使用方法正確,但是我在讀取時使用的是java.net.URLEncoder.encode,即讀取和存取均用java.net.URLEncoder.encode,導致存入的中文正確,而讀取顯示時出現亂碼。本文代碼已修改,其中亂碼錯誤地方已標識。
運行正確結果截圖如下: