一、Servlet簡介:html
●Servlet是一個符合特定規範的 JAVA 程序 , 是一個基於JAVA技術的Web組件。java |
●Servlet容許在服務器端,由Servlet容器所管理,用於處理客戶端請求並作出響應。程序員
|
●Servlet容器:Servlet容器也稱爲 Servlet引擎,是 WEB 服務器或應用程序服務器的一部分,用於在發送的請求和響應之上提供網絡服務。web ●管理和運行 Servlet/JSP的容器也稱Web容器;算法 ●Servlet容器、JSP 容器和 Web容器是同義的;數據庫 |
●Servlet主要用於生成動態的內容,他能夠接受和處理請,求並動態生成 HTML 內容對客戶端進行響應; 瀏覽器
|
二、Servlet與 JSP 的關係:服務器
●在使用JSP技術開發 WEB 程序時,咱們所要作的是在 JSP 中寫入 JAVA 代碼,當服務器運行JSP時,將JSP轉換成JAVA類並編譯執行,動態獲取數據生成 HTML 代碼 , 最終顯示在客戶瀏覽器上。cookie
|
|||
|
|||
●Servlet繼承javax.servlet.http.HttpServlet類: eg:
分析:JSP 在運行時會被 Web容器譯爲一個Servlet,動態響應內容是經過運行這個Servlet類產生的,Servlet是 JAVA Web動態交互術的關鍵組件,也是 JSP 的技術基礎,容器在運行 JSP 時,須要先將其內容翻譯成 Servlet的語法,再按照Servlet的方式運行; |
|||
●Servlet體系結構:
|
三、Servlet API:
●Servlet API包含在兩個包內, javax. Servlet包中的類和接口是通用的不依賴協議的 Servlet API,包括 Servlet、ServletRequest、ServletResponse、ServletConfig、ServletContext接口及抽象類GenericServlet , javax.servlet.http包中的類和接口是用於支持 HTTP協議的Servlet API; |
||||||||||||
●Servlet接口:定義了全部Servlet須要實現的方法;
|
||||||||||||
●GenericServlet抽象類:提供了Servlet接口和ServletConfig接口,給出了方法的默認實現(service( )方法除外);定義了通用的、不依賴於協議的Servlet。
★一般只須要重寫不帶參的init()方法,若是重寫init(ServletConfig config)方法,則應包含super.init(config)代碼; ★若是要編寫一個通用的Servlet,只要繼承自GenericServlet類,實現service()方法便可; |
||||||||||||
●HttpServlet抽象類:大多數的網絡應用是經過 HTTP協議訪問服務器資源的,所以咱們編寫的 Servlet大多也是應用於處理 HTTP協議的請求和響應。 ★抽象類HttpServlet 繼承自GenericServlet類,具備與GenericServlet相似的方法,並提供了與 HTTP相關的實現,支持對HTTP的POST、GET 等請求方式進行差別化處理;開發中,若是須要編寫 Servlet,主要就是繼承 HttpServlet 抽象;
★HttpServlet的service (HttpServletRequest req, HttpServletResponse res )方法至關於一個分發器,能夠根據請求方法的類型,調用相應的doXxx()方法。因此在編寫Servlet時只須要根據應用的須要,重寫doGet()或者doPost()方法便可; |
||||||||||||
●ServletConfig接口:Servlet容器使用ServletConfig在Servlet初始化過程當中獲取配置信息,一個Servlet只有一個ServletConfig對象;
|
||||||||||||
●ServletContext 接口: ★一個 ServtetContext接口的實例表示一個 Web 應用的上下文,Sewlet 使用 Servletontext 接口定義的方法與它的 Servlet 容器進行通訊。JSP 內置對象application就是 ServletContext的實例。 ★Servlet 容器廠商負責提供 ServletContext 接口的實現,容器在應用程序加載時建立ServletContext對象,ServletContext 對象被 Sefvlet 容器中的全部Sefvlet共享。
|
■請求、響應相關接口:ServletRequest 和 HttpServletRequest 接口:
|
||||||||||||||||||||
★ServletRequest 接口:當客戶請求時,由 Servlet 容器建立 ServletRequest 對象用於封裝客戶的請求信息,這個對象將容器做爲 service ( ) 方法的參數之一傳遞給 Servlet , Servlet 可以利用 ServletRequest 對象獲取客戶端請求數據。
|
||||||||||||||||||||
★HttpServletRequest接口:HttpServletReqiest 位於 javax.servlet.http包中,繼承自ServletRequest 接口,經過該接口一樣能夠獲取請求中的參數。HttpServletRequest 接口除了繼承了ServletRequest 接口中的方法,還增長了一些用於讀取請求信息的方法;
|
||||||||||||||||||||
■ServletResponse 和 HttpServletResponse 接口: |
||||||||||||||||||||
★ServletResponse接口:Servlet 容器在接收客戶請求時,除了建立 ServletRequest 對象用於封裝客戶的請求信息外,還建了一個 ServletResponse 對象,用於封裝響應數據,而且同時將這兩個對象一併做爲參數傳遞給Servlet。Servlet利用ServletRequest 對象獲取客戶端的請求數據,通過處理後由 ServletResponse 對象發送響應數據;
★HttpServletResponse:與 HttpServletRequest 接口相似,HttpServletResponse 接口也繼承自 ServletResponse 接口,用於客戶端的請求執行響應。它除了具備ServletResponse接口的經常使用方法外、還增長了新的方法;
|
四、Servlet的應用:
●建立Servlet ★繼承HttpServlet ★重寫doPost()或doGet()方法 ● 部署Servlet ★編譯Servlet到/WEB-INF/classes目錄 ★編輯部署描述文件web.xml <servlet> <servlet-name> Servlet的名字</servlet-name> <servlet-class> Servlet 類的徹底限定名</servlet-class> </servlet> <servlet-mapping> <servlet-name>給出 Servlet 的名字,必須與在< servlet >元素中聲明的Servlet 名字相同</servlet-name> <url-pattern>指定 Servlet 的 URL</url-pattern> </servlet-mapping> ●啓動Tomcat,訪問Servlet |
●建立Servlet: eg:建立一個用於獲取用戶名並向頁面輸出的Servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HttpServletTest extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 在Tomcat中配置URIEncoding解決GET方式的中文亂碼,代碼中再也不作處理 String uName = request.getParameter("username"); if (uName == null) { uName = "遊客"; } // 設置響應內容的類型並指定字符集,以避免瀏覽器展現中文內容時出現亂碼 response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); out.println("<html>"); out.println(" <head><title>Servlet</title></head>"); out.println(" <body>"); out.println("你好,歡迎" + uName + "來到Servlet世界"); out.println(" </body>"); out.println("</html>"); out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 對POST方式提交的數據統一設置字符集,解決中文亂碼問題 request.setCharacterEncoding("UTF-8"); doGet(request, response); } } 分析:在上面的示例中,須要強調如下三點: ★開發 Servlet 時,首先要導入 Servlet 所需的包; ★自定義的 Servlet 類繼承自 HttpServlet 類; ★實現 doGet ()或者 doPost()方法; ▲My Eclipse下Servlet中方法的實現:選中source——Override/Implement Methods…——選擇須要實現的方法——OK; 如圖:
技巧:HTTP請求經過使用 GET 或 POST 方法提交,相應地在 Servlet 中也提供了 doGet()和 doPost()兩種分別處理請求的方法,但實際的處理過程不少時候卻幾手是相同的,所應一般的處理方法是:分別編寫 doGet )和 doPost ()方法對應不一樣的提交方式,同時經過相互調用避免重複編碼。例如,把處理代碼都寫在 doGet()方法中, 而後在 doPost()方法調用 doGet ()方法。這樣就能保證既能對不一樣提交方式進行差別化處理,又能夠避免代碼冗餘; |
●部署 Servlet:首先應編輯 Web 應用的部署描述文件 web.xml,添加對示例 3 中 Servlet 類的配置,該文件在程序運行Servlet時起着一個 ‘總調度" 的角色 , 它會告訴容器如何建立和訪問 Servlet。在 web. xml 文件中配置 Servlet 須要使用兩個 XML 元素 < servlet >和<servlet-mapping>。 其中<servlet>元素把Servlet 全類名 ( 包名+類名) 映射到一個內部名稱,而< servlet –mapping>元素則將某個 URL 映射到Servlet 的內部名稱; eg:web. xml 文件的關鍵代碼以下: <servlet> <servlet-name>HttpServletTest</servlet-name> <servlet-class>cn.store.servlet.HttpServletTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>HttpServletTest</servlet-name> <url-pattern>/HttpServletTest</url-pattern> </servlet-mapping> 分析:在示例中,web.xml 文件中使用了< servlet >和<servlet-mapping>兩個 XML 元素把用戶訪問的URL 映射到 Servlet, ◆詳細介紹這兩個元素及其子元素: 1)、在 web.xml文件中, < servlet >元素可包含多個子元素,其中<servlet-name>指定 Servlet的名字 , 這個名字在同一個 Web 應用中必須惟一,<servlet-class>指定 Servlet 類的徹底限定名; 2)、<servlet-mapping>元素在 Servlet 和 URL 之間定義映射,它包含兩個子元素<servlet-name>和<url-pattern>: ★<servlet-name>給出 Servlet 的名字,必須與在< servlet >元素中聲明的Servlet 名字相同, ★<url-pattern>元素指定 Servlet 的 URL , 須要特別注意的是,該路徑是相對於 Web 應用程序的路徑,在配置Servlet 與 URL的映射後,當 Servlet 容器接收到一個請求時,對請求的路徑和Servlet映射的路徑進行匹配,進而調用具體Servlet類的相關方法。 ◆下面介紹在web.xml 中經常使用<url-pattern>設置方法: ▲<url-pattern>/xxx</url-pattern>精確匹配 , 如<url-pattern>/ helloServlet </url-pattern>; ▲<url-pattern>/xxx/*</url-pattern>,路徑匹配,若是沒有精確匹配,對/xxx/路徑的全部請求將由該 Servlet 進行處理,如<url-pattern>/ helloServlet/* </url-pattern>,; ▲<url-pattern>*.xxx</url-pattern>若是沒有精確匹配和路徑匹配,則全部針對. xxx擴展名的請求將由該 Servlet 處理;
◆擴展:有時需指定在容器啓動時 Servlet 的加載次序,能夠在<servlet>元素中增長<load-on-startu>元素。該元素的值必須是整數,若是爲負數或沒有指定這個元素,容器將在客戶端首次訪問 Servlct 時進行加載;若是爲正數或0;客器將在啓動時根據值的順序加載 Servlet,且值越小加載優先級越高; |
●訪問 Servlet: eg:部署完 Servlat 後,下面介紹如何訪問 Servlet, 建立 index . jsP 頁面代碼以下: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>ServletTest</title> </head> <body> <form action="HttpServletTest" method="post"> 姓名:<input type="text" name="username" /> <input type="submit" value="提交"/> </form> </body> </html> 分析:在上面的代碼中,表單提交的路徑 (action 屬性 ) 指向 web.xml 文件中<url-pattern>元素所指定的URL, 便可訪問對應的 Servlet。 ★部署項目並啓動 Tomcat 後,打開瀏覽器,在地址欄中 輸入 ’ http//localhost8080/store/index. jsp" 輸入用戶姓名爲 "小菜包',頁面會顯示:你好,歡迎小菜包來到 Servlet世界; ★若是根據 web . xml 中設置的 URL 輸入 「 http//localhost : 8080/store/HttpServletTest直接訪Servlet , 根據「訪問Servlet」的下面的代碼,在運行時若是沒有傳遞 username 參數就會默認輸出 '遊客" ,頁面會顯示:你好,歡迎遊客來到 Servlet世界; ◆提示:若是但願 Web 應用起始訪問的是 Scrvlet, 則能夠在 web.xml 文件中進行配置, eg:<welcome-file-list> <welcome-file>HttpServletTest</welcome-file> </welcome-file-list> 這時在瀏覽器中輸入 "http://localhost:8080/store’ :運行效果一樣是(頁面會顯示):你好,歡迎遊客來到 Servlet世界; |
技巧:爲了方便管理,一般將建立的 Servlet 單獨放在一個包中,如 cn.store.servlet。 ★經過 IDE工具能夠快速建立和部署 Servlet: 右擊專門存放 Servlet 的包——New——Servlet——Name: XxxServletName (爲建立的 Servlet 命名)——Next ( 此步驟的窗口信息用於部署 web.xml , 配置 Servlet 能夠選擇各項的默認值,也能夠根據須要修改Servlet名稱和 Servlet的映射路徑,即修改’Servlet/JSP Name:' 和’ Servlet/JSP Mapping URL:',對於 「Display Natne:」和 「Description 「後面的解釋內容, 能夠刪除)——Finish; ★用工具建立的Servlet只是一個Servlet模扳,能夠根據業務需求編寫; |
五、使用 Servlet 實現控制器:
●Servlet與 JSP 的區別: ★JSP文件在用戶第一次請求時會被編譯成Servlet, 而後由這個Servlet處理用戶的請求,因此 JSP 也能夠當作是運行時的Servlet; ★JSP 和 Servlet 的區別: ◆JSP頁面在 HTML 元素中嵌入Java腳本代碼和 JSP 標記,比使用傳統Servlet技術開發表示層更加容易。JSP的部署也更加簡單,JSP容器 (Servlet容器)會對擴展名是.jsp的URL統一配置,將其轉換爲 Servlelt爲客戶端服務,無需爲每個 JSP 文件配置 URL 映射; ◆JSP 頁面 HTM元素與 java腳本混合的語法 , 對於請求處理過程當中編寫流程控制代碼,數據訪問代碼等倒是不利的,難以模塊化開發及重用,此時更適合採用傳統 Java 類的形式進行開發。所以使用 Servlet 在服務器上解釋和執行瀏覽器的請求,充當客戶端和其餘層之間的中間層角色更加合適; ◆經過上面的分祈,Servlet 和 JSP 各有所長,JSP 能夠方便地開發表示層組件. 而Servlet適合編寫流程控制代碼. 在開發 Wab 應用時,能夠針對二者的特點結合使用,合理分工; |
●實現Servlet控制器: ★使用 JSP 來作控制頁, 主要功能是流程控制和業務邏輯處理,如今能夠將這部分代碼提取出來由Servlet來完成,應用的架構以下圖:
★Servlet充當控制器的角色,它接受請求、負責實例化 JavaBean 對象對業務邏輯進行處理,併爲JSP頁面準備封裝的JavaBean對象,接着將請求分發給適當的JSP頁面來產生響應; |
◆技巧:request.getContextPath()能夠獲取當前web 應用的上下文路徑. 對於經由瀏覽器請求的URL , 使用應用上下文路徑進行約束,能夠避免使用相對路徑時可能發生的路徑解析錯誤; eg: ‘location.href=「’contextPath+「 /util/topics?opr=list’」 對於轉發方法使用的 URL, 能夠直接以 「/」 開始以表示當前應用的根路徑; |
六、Servlet的生命週期:
●Servlet的生命週期是經過 Servlet接口中的 init()、servicef()和 destroy()方法來表示的;即 Servlet從建立到銷毀的過程,包括如何加載和實例化、初始化、處理請求以及如何被銷燬;
◆加載和實例化:Servlet不能獨立運行,它必須被部署至Servlet 容器中,由容器實例化和調用 Servlet 的方法,Servlet容器在 Servlet的生命週期內管理 Servlet,當Servlet容器啓動或者當客戶端發送一個請求時, Servlet容器會查找內存中是否存在Servlet的實例, 若是不存在,就建立一個 Servlet實例,若是存在該Servlet的實例,就直接從內存中取出該實例響應請求; ◆初始化:在Servlet容器完成 Servlet 實例化後,Servlet容器將調用 Servlet的 init()方法進行初始化,初始化的目的是讓Servlet對象在處理客戶端請求前完成一些準備或資源預加載工做,如設置數據庫鏈接參數,創建 JDBC 鏈接,或者是創建對其餘資源的引用。 ★注:對於每個Servlet實例 init()方法只能被調用一次; ◆服務:Servlet被初始化後 , 就處於能響應請求的就緒狀態,當Servlet容器接收客戶端請求時,調用Servlet的 service()方法處理客戶端請求,HttpServlet 的service()方法會根據 GET 或 POST 請求轉調doGet()或 doPost()方法,Servlet實例經過 ServletRequest 對象得到客戶端的請求,經過調用ServletResponse 對象的方法設置響應信息; ◆銷燬:Servlet 的實例是由 Servlet 容器建立的,因此實例的銷燬也是由容器來完成的,Servlet容器判斷一個 Servlet容器是否應當被釋放時(容器關閉或須要回收資源),容器就會調用 Servlet 的 destroy()方法,該方法指明哪些資源能夠被系統回收,而不是由 destroy()方法直接回收 Servlet 實例; |
●Servlet 生命週期演示:
eg:Servlet生命週期的各個方法的調用過程: import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloServlet extends HttpServlet { //構造方法 public HelloServlet() { super(); } //初始化方法 public void init() throws ServletException { System.out.println("初始化時,init()方法被調用!"); } //doGet()方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("處理請求時,doGet()方法被調用。"); } //doPost()方法 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("處理請求時,doPost()方法被調用。"); } //用於釋放資源 public void destroy() { super.destroy(); System.out.println("釋放系統資源時,destroy()方法被調用!"); } } 分析:運行本段代碼,打開瀏覽器,根據 web.xml 中設置的URL映射訪問HelloServlet。由於HelloServlet只在控制檯進行輸出, 運行效果:信息:Server startup in 2449 ms 初始化時,init()方法被調用! 處理請求時,doGet()方法被調用。 從新提交一次請求,控制檯顯示的信息以下: 信息:Server startup in 2449 ms 初始化時,init()方法被調用! 處理請求時,doGet()方法被調用。 當再一次提交請求時, Servlet 的init()方法沒有被執行,這說明 init ()方法只有在加載當前的Servlet時候被執行,而且只被執行一次。 當中止Tomcat服務,destroy()方法被執行,顯示信息:釋放系統資源時,destroy()方法被調用! |
七、 初始化參數及訪問應用上下文:
●得到 Servlet 初始化參數: ★配置 Servlet時,能夠對該 Servlet 設置初始化參數,經過初始化參數能夠更靈活地控制 Servlet的運行時行爲; ▲設置初始化參數須要修改 web .xml文件,在<servlet>元素中增長<init-param>元素, eg: <web-app version="3.0" <servlet> <servlet-name>HelloServlet</servlet-name <servlet-class>demo.servlet.HelloServlet</servlet-class> <init-param> <param-name>initParam</param-name> <param-value>Hello Servlet</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/HelloServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>HelloServlet</welcome-file> </welcome-file-list> </web-app> 說明:定義Servlet 的初始化參數時使用<init-param>元素,<init-param>元素是<servlet>元素子元素,使用<init-param>元素必須包括<param-name>元素和 <param-value>元素;<param-name>元素定義初始化參數的名字;<param-value>元素指定初始化參數的值; |
◆初始化參數在 servlet 的初始化環節被加載,並可經過 ServletConfig 實例的 getlnitParameter (String name)方法進行訪問; eg: public class HelloServlet extends HttpServlet { //構造方法 public HelloServlet() { super(); } //初始化方法 public void init() throws ServletException { System.out.println("初始化時,init()方法被調用!"); } //doGet()方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("處理請求時,doGet()方法被調用。"); String initParam = getInitParameter("initParam"); System.out.println(initParam); } //doPost()方法 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("處理請求時,doPost()方法被調用。"); } //用於釋放資源 public void destroy() { super.destroy(); System.out.println("釋放系統資源時,destroy()方法被調用!"); } } 分析:經過 GenericServlet 中定義的 getlnitParameter(String nmne) 方法獲取初始化數,該方法其實是經過調用 ServletConfig 的getlnitParametcr(String name)方法來獲取始化參數值,比 getServletConfig.getlnitParamater(String name)的完整寫法更加簡潔方便; 部署web項目並訪問HelloServlet。運行進行結果如圖:
|
◆得到上下文參數: 爲某個Servlet定義的初始化參數只能被Servlet訪問,若是該參數須要被更多的Web應用組件訪問,可使用上下文參數定義,要定義上下義參數一樣須要對web. xml 文件進行修改; eg: <web-app version="3.0" <context-param> <param-name>contextParam</param-name> <param-value>ContextParamValue</param-value> </context-param> <!--省略其餘配置--> </web-app> 說明:使用<context-param>元素聲明 Web應用全局範圍參數,<context-param>元素包括<param-name>元素和<param-value>元素; <param-name>素指定參數的名字 , <param-value>元素指定參數的值; |
八、 總結:
|