本節書摘來異步社群《java ee 7精粹》一書中的第2章,第2.1節,作者:【美】arun gupta,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
servlet是一種托管在servlet容器的web元件,可以生成動态内容。web用戶端使用請求/響應模式與servlet互動。servlet容器負責servlet的生命周期,接收請求和發送響應,并執行這一過程中所需的編碼/解碼。
servlet類是使用@webservlet注解并繼承javax.servlet.http.httpservlet類的pojo。
下面是一個servlet定義的示例:

預設的servlet名是完全限定的類名,可使用注解的name屬性覆寫。servlet可以部署在多個url:
@webinitparam可以用于指定servlet的初始化參數:
httpservlet接口為每個http請求:get、post、put、delete、head、options和trace的處理,提供了一個doxxx方法。通常情況下,開發人員隻關注覆寫doget和dopost方法。下面的代碼顯示了處理get請求的servlet。
在這段代碼中:
httpservletrequest和httpservletresponse捕獲web用戶端的請求/響應。
可以從httpservletrequest中擷取請求參數,http頭,請求路徑的不同部分如主機名稱、端口和上下文,以及更多的資訊。
同時,可以發送和檢索http cookie。開發人員負責填充httpservletresponse,然後容器将捕獲的http頭資訊或體消息發送給用戶端。
這段代碼顯示了servlet接收的http get請求是如何顯示一個簡單的響應給用戶端的。
請求參數可以由get和post請求傳遞。在一個get請求中,這些參數通過鍵/值對形式的查詢字元串來傳遞。下面是一個使用請求參數調用前述servlet的url示例:
在一個post請求中,請求參數也可以通過編碼在請求體的post資料中來傳遞。get和post的請求參數都可以從httpservletrequest中獲得:
每次請求的請求參數可以不同。
初始化參數也被稱為init params,可以在servlet上定義來存儲啟動和配置資訊。如前所述,@webinitparam用于為一個servlet指定初始化參數:
可以通過覆寫javax.servlet.servlet接口的生命周期調用方法init、service和destroy來操控servlet的預設行為。通常情況下,資料庫連接配接的初始化發生在init方法中,資料庫連接配接的釋放發生在destroy方法中。
還可以使用web應用程式的部署描述檔案web.xml中的servlet和servlet-mapping元素定義servlet。如下,在web.xml中定義了一個account servlet:
注解配置的方式覆寫了大部分的常見用例,是以web.xml不是必需的。但某些情況下web.xml是必需的,例如指定servlet的順序隻能使用web.xml中完成。
如果web.xml中的metadata-complete元素的值設定為true,那麼類中定義的注解将不被處理:
在部署描述檔案web.xml中定義的值會覆寫使用注解定義的值。
servlet被打包在一個以.war檔案形式存在的web應用程式中。多個servlet可以被打包在一起,他們共享一個servlet上下文。servlet上下文類servletcontext中提供了有關servlet運作環境的詳細資訊,用于與容器通信。例如,讀取封裝在web應用程式中的資源、寫入日志檔案或者分派一個請求。
可以從httpservletrequest中獲得servletcontext執行個體:
為實作session跟蹤,servlet可以發送一個名為jsessionid的http cookie到用戶端。這個cookie可以标記為httponly,進而確定cookie不會暴露給用戶端的腳本代碼,是以有助于減輕多種跨站腳本的攻擊:
此外,servlet可以使用url rewriting作為session跟蹤的基礎。servletcontext. getsessioncookieconfig方法傳回一個sessioncookieconfig執行個體,該執行個體可以用于配置cookie的不同屬性。
httpsession接口用于檢視和操控有關session的資訊,比如session辨別符和建立時間,并且可以将對象綁定到session中。如下,建立了一個新的session對象:
<code>session.setattribute</code>和<code>session.getattribute</code>方法用于将對象綁定到session中。
如果需要進一步處理一個請求,<code>servlet</code>可以将該請求轉發(forward)到另一個<code>servlet</code>中。使用<code>requestdispatcher</code>可以将請求分派到不同的資源中,<code>requestdispatcher</code>執行個體可以從<code>httpservletrequest.getrequestdispatcher</code>方法或者<code>servletcontext. getrequestdispatcher</code>方法中獲得。前者可以接受相對路徑,而後者可以接受目前上下文的相對路徑:
在這段代碼中,bank代指部署在相同上下文中另一個<code>servlet</code>。
<code>servletcontext.getcontext</code>方法可以獲得不同上下文的<code>servletcontext</code>執行個體。從中可以獲得<code>requestdispatcher</code>執行個體來分派該上下文的請求。
可以通過調用<code>httpservletresponse.sendredirect</code>方法重定向(redirect)一個<code>servlet</code>響應到另一個資源。這個臨時的重定向響應到用戶端,然後用戶端發出一個新的請求到指定的url。注意,在本例中,原始請求的對象在重定向的url中不可用。重定向可能會稍微慢一些,因為它需要用戶端發送兩次請求,而轉發(forward)是在容器内進行的:
在這裡,響應重定向到<code>http://example.com/someotherservlet</code>。注意,這個url可以是不同的主機/端口,并且可以向容器發送相對或絕對路徑。
除了使用<code>@webservlet</code>和<code>web.xml</code>聲明<code>servlet</code>,也可以使用<code>servletcontext.addservlet</code>方法以程式設計方式來定義。該方法可以編碼在<code>servletcontainerinitializer.onstartup</code>方法或者<code>servletcontextlistener.contextinitialized</code>方法中。event listeners一節有更多的描述。
當應用程式啟動時,使用給定的<code>servletcontext</code>調用<code>servletcontainerinitializer. onstartup</code>方法。<code>addservlet</code>方法傳回<code>servletregistration.dynamic</code>,用于建立url映射、設定安全角色、設定初始化參數和管理其他配置項: