Servlet是JavaEE三大組建之一,是使用Java語言編寫服務器端的程序,主要用來處理Web應用程序中的請求-響應。Servlet並無main之類的執行方法,當用戶訪問服務器的時候,Tomcat是經過調用Servlet的某些方法來完成整個處理過程的。Servlet是運行在Tomcat服務器提供的Servlet容器中的,因此Servlet是不用程序指定調用的。html
JavaEE的版本與Tomcat服務器的版本是存在一種對應關係的,在開發Web應用程序的時候,須要注意對應版本關係,否則可能引發Web程序報錯。java
JavaEE與Tomcat服務器的版本對應關係以下表:web
Tomcat服務器版本apache |
Servlet\JSP版本api |
JavaEE版本瀏覽器 |
Java運行環境tomcat |
Tomcat 4.1服務器 |
Servlet 2.3\JSP 1.2mvc |
JavaEE 1.3app |
JDK 1.3 |
Tomcat 5.0 |
Servlet 2.4\JSP 2.0 |
JavaEE 1.4 |
JDK 1.4 |
Tomcat 5.5\6.0 |
Servlet 2.5\JSP 2.1 |
JavaEE 5.0 |
JDK 5.0 |
Tomcat 7.0 |
Servlet 3.0\JSP 2.2 |
JavaEE 6.0 |
JDK 6.0 |
2. 編寫一個Servlet
開發工具Eclipse或MyEclipse自己提供了建立Servlet的功能,下面咱們首先利用開發工具來建立一個Servlet,具體步驟以下:
該界面是配置Servlet在web.xml文件中的相關信息,具體內容以下:
Servlet/JSP Class Name:Servlet的完整路徑。
Servlet/JSP Name:Servlet的名稱。
Servlet/JSP Mapping URL:配置Servlet攔截的路徑,客戶端經過該路徑訪問Servlet。
File Path of web.xml:當前工程的web.xml配置文件保存路徑。
Display Name:顯示名稱。
Description:描述名稱。
建立完成以後,當前Web工程的變化是在src目錄下多了一個Servlet的Java文件,在WEB-INF目錄中的web.xml文件中多了Servlet相關配置信息。
將當前Web應用程序發佈到Tomcat服務器,並啓動Tomcat服務器運行測試當前建立的Servlet內容。
經過Eclipse或MyEclipse建立Servlet雖然簡單,但咱們並不知道相關代碼是什麼含義。因此,下面咱們須要研究一下生成出來的代碼。
首先, 咱們來研究一下建立的Servlet文件源代碼,會發現以下內容:
根據上述內容,咱們能夠手動建立一個Servlet的Java文件,以下面的代碼所示:
1 public class SecondServlet extends HttpServlet { 2 @Override 3 public void init() throws ServletException { 4 System.out.println("這是init()方法..."); 5 } 6 @Override 7 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 8 throws ServletException, IOException { 9 System.out.println("這是doGet()方法..."); 10 } 11 @Override 12 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 13 System.out.println("這是doPost()方法..."); 14 } 15 @Override 16 public void destroy() { 17 System.out.println("這是destroy()方法..."); 18 } 19 }
其次,咱們再來研究一下web.xml配置文件增長的內容:
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 7 <display-name></display-name> 8 <servlet> 9 <description>This is the description of my J2EE component</description> 10 <display-name>This is the display name of my J2EE component</display-name> 11 <!-- 12 servlet標籤:用於配置Servlet的名稱和完整路徑. 13 * servlet-name標籤:用於爲對應的Servlet設置名稱. 14 * servlet-class標籤:用於設置對應的Servlet的完整路徑. 15 --> 16 17 <servlet-name>FirstServlet</servlet-name> 18 <servlet-class>app.java.servlet.FirstServlet</servlet-class> 19 </servlet> 20 <!-- 21 servlet-mapping標籤:用於配置Servlet攔截客戶端請求路徑. 22 * servlet-name標籤:用於設置對應使用的Servlet名稱. 23 * url-pattern標籤:用於設置客戶端請求的攔截路徑. 24 * 相對路徑:/servlet/FirstServlet 25 * 絕對路徑:http://localhost:8080/08_servlet/servlet/FirstServlet 26 --> 27 28 <servlet-mapping> 29 <servlet-name>FirstServlet</servlet-name> 30 <url-pattern>/servlet/FirstServlet</url-pattern> 31 </servlet-mapping> 32 <welcome-file-list> 33 <welcome-file>index.jsp</welcome-file> 34 </welcome-file-list> 35 </web-app>
將當前Web應用程序發佈到Tomcat服務器,並啓動Tomcat服務器運行測試當前建立的Servlet內容。
經過建立Servlet的Java文件中的代碼內容,能夠發現建立的Servlet是繼承於HttpServlet類,查看JavaEE幫助文檔中的HttpServlet內容。
Method Summary |
|
protected void |
doGet(HttpServletRequest req, HttpServletResponse resp) |
protected void |
doPost(HttpServletRequest req, HttpServletResponse resp) |
protected void |
service(HttpServletRequest req, HttpServletResponse resp) |
void |
service(ServletRequest req, ServletResponse res) |
經過幫助文檔提供的內容,咱們能夠知道建立Servlet中的doGet和doPost方法是繼承於HttpServlet提供的,但還有init和destroy方法沒有找到。咱們發現HttpServlet是繼承於GenericServlet,查看JavaEE幫助文檔中的GenericServlet內容。
Method Summary |
|
void |
destroy() |
void |
init() |
abstract void |
service(ServletRequest req, ServletResponse res) |
經過幫助文檔提供的內容,咱們能夠知道init和destroy方法是源於GenericServlet。可是其實GenericServlet都實現了Servlet接口。
Method Summary |
|
void |
destroy() |
getServletConfig() |
|
getServletInfo() |
|
void |
init(ServletConfig config) |
void |
service(ServletRequest req, ServletResponse res) |
因此,init和destroy方法是Servlet接口提供的方法。經過上述的查找,咱們已經很清晰的知道了Servlet的繼承關係,具體以下圖:
利用Servlet完成的Web應用的實際工做流程是經過Tomcat服務器發佈服務,客戶端與服務器端之間的交互遵循Http協議完成的。具體工做流程以下:
咱們也能夠經過下面的圖來理解Servlet具體的工做流程。
值得注意的是Servlet內容是屬於JavaEE內容,和使用JavaSE內容同樣,都是須要引入JAR包的。使用Eclipse或MyEclipse建立Web應用程序的時候,會發現已經導入了JavaEE所須要的JAR包。其中javaee.jar包中包含了使用Servlet的全部內容。
可是,當把Web應用程序發佈到Tomcat服務器的時候,發現對應的目錄中並無javaee.jar包。咱們知道不管是編譯仍是運行都是須要這些JAR包的,這說明Tomcat服務器自己提供了Servlet運行所須要的環境。在Tomcat服務器的安裝目錄中的lib目錄中能夠找到servlet-api.jar包,該JAR包也提供了Servlet運行所需的環境。
咱們若是想要手動編譯Servlet的話,須要作如下及步:
javac -classpath C:\Tools\apache-tomcat-7.0.55\lib\servlet-api.jar -d . Servlet.java
通常狀況下,自定義Servlet都是繼承HttpServlet。但經過HttpServlet的繼承鏈,咱們知道HttpServlet是實現了Servlet接口,下面列表是Servlet接口提供的全部方法。
Method Summary |
|
void |
destroy() |
getServletConfig() |
|
getServletInfo() |
|
void |
init(ServletConfig config) |
void |
service(ServletRequest req, ServletResponse res) |
上述全部方法中,init()、service()和destroy()方法叫作Servlet的生命週期。討論一下有關生命週期的三個方法:
在Servlet實例化以後,Servlet容器會調用init()方法,主要是用來完成處理客戶端請求以前的初始化工做。init()方法在Servlet的生命週期中只被執行一次。
Servlet容器調用service()方法來處理客戶端發送的請求。在service()方法被調用以前,必須保證init()方法被正確執行。service()方法在每次客戶端發送請求以後,會被執行一次。
當Servlet容器檢測到當前Servlet實例被移除時,會調用destroy()方法,以便讓Servlet實例能夠釋放所使用的全部資源。destroy()方法在Servlet的生命週期中也只被執行一次。
下面我經過實際操做來討論關於Servlet的生命週期是怎麼樣的:
1 public class LifeServlet implements Servlet { 2 3 public LifeServlet(){ 4 System.out.println("這裏建立了一個Servlet實例對象..."); 5 } 6 7 public void init(ServletConfig config) throws ServletException { 8 System.out.println("這是init()方法..."); 9 } 10 11 public void service(ServletRequest req, ServletResponse res) 12 throws ServletException, IOException { 13 System.out.println("這是service()方法..."); 14 } 15 16 public void destroy() { 17 System.out.println("這是destroy()方法..."); 18 } 19 20 public ServletConfig getServletConfig() { 21 return null; 22 } 23 public String getServletInfo() { 24 return null; 25 } 26 }
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <servlet> <servlet-name>LifeServlet</servlet-name> <servlet-class>app.java.servlet.LifeServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LifeServlet</servlet-name> <url-pattern>/servlet/LifeServlet</url-pattern> </servlet-mapping> </web-app>
五月 12, 2017 7:34:26 下午 org.apache.catalina.core.AprLifecycleListener init
信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: E:\MyEclipse 2016 CI\binary\com.sun.java.jdk8.win32.x86_1.8.0.u66\bin;D:\tomcat\bin
五月 12, 2017 7:34:27 下午 org.apache.coyote.AbstractProtocolHandler init
信息: Initializing ProtocolHandler ["http-bio-8080"]
五月 12, 2017 7:34:27 下午 org.apache.coyote.AbstractProtocolHandler init
信息: Initializing ProtocolHandler ["ajp-bio-8009"]
五月 12, 2017 7:34:27 下午 org.apache.catalina.startup.Catalina load
信息: Initialization processed in 842 ms
五月 12, 2017 7:34:27 下午 org.apache.catalina.core.StandardService startInternal
信息: Starting service Catalina
五月 12, 2017 7:34:27 下午 org.apache.catalina.core.StandardEngine startInternal
信息: Starting Servlet Engine: Apache Tomcat/7.0.11
五月 12, 2017 7:34:27 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory day11
五月 12, 2017 7:34:27 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory docs
五月 12, 2017 7:34:27 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory examples
五月 12, 2017 7:34:27 下午 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: contextInitialized()
五月 12, 2017 7:34:27 下午 org.apache.catalina.core.ApplicationContext log
信息: SessionListener: contextInitialized()
五月 12, 2017 7:34:27 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory host-manager
五月 12, 2017 7:34:28 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory manager
五月 12, 2017 7:34:28 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory ROOT
五月 12, 2017 7:34:28 下午 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory webmvcframework
五月 12, 2017 7:34:28 下午 org.apache.coyote.AbstractProtocolHandler start
信息: Starting ProtocolHandler ["http-bio-8080"]
五月 12, 2017 7:34:28 下午 org.apache.coyote.AbstractProtocolHandler start
信息: Starting ProtocolHandler ["ajp-bio-8009"]
五月 12, 2017 7:34:28 下午 org.apache.catalina.startup.Catalina start
信息: Server startup in 1061 ms
經過上述操做,能夠發現:在第一次向Servlet發送請求時,Tomcat服務器的Servlet容器首先建立Servlet實例對象,再進行Servlet初始化工做,最後調用service()方法來處理請求。第二次向Servlet發送請求時,只調用了service()方法,並無執行Servlet的構造方法和init()方法。在中止Tomcat服務器時,Servlet的destroy()方法被調用,釋放所使用的資源。