現(xiàn)在學習Servlet,我的主要目的是做整體了解,作為學習SSM的熱身,所以本篇的目的是以一篇文章實現(xiàn)對servlet的基本概括。
簡介
java servlet是運行在Web 服務器或應用服務器上的程序,是一個中間層,介于web瀏覽器(HTTP客戶端)——HTTP服務器上的數(shù)據(jù)庫或應用程序之間
本質(zhì)上,servlet是運行在web服務器上的java類,Servlet 可以使用 javax.servlet 和 javax.servlet.http 包創(chuàng)建
任務
Servlet主要執(zhí)行以下任務:
- 讀取B/C發(fā)送的HTTP請求數(shù)據(jù)(表單、cookies等)
- 處理請求生成結果,通過訪問數(shù)據(jù)庫、計算、遠程調(diào)用等方式產(chǎn)生結果
- 發(fā)送給B/C相關的HTTP答復
生命周期
-
init()
進行Servlet初始化,方法只被調(diào)用一次;
Servlet創(chuàng)建于用戶第一次調(diào)用對應該Servlet的URL,當然也可以指定Servlet在服務器第一次啟動時即加載;
用戶調(diào)用一個Servlet時,就會創(chuàng)建一個Servlet實例,每次請求都會產(chǎn)生一個新的線程,適當?shù)臅r候交給doGet或doPost
-
service()
執(zhí)行任務的主要方法,容器調(diào)用service()處理客戶端請求并將格式化的響應返回客戶端;
一個Servlet請求會有一個線程,線程內(nèi)會調(diào)用本方法檢查HTTP請求類型,并在適當時候調(diào)用doGet、doPost等方法
-
destroy()
在此Servlet將終止,使得Servlet 關閉數(shù)據(jù)庫連接、停止后臺線程、把 Cookie 列表或點擊計數(shù)器寫入到磁盤,并執(zhí)行其他類似的清理活動,僅被調(diào)用一次;
調(diào)用此方法后,Servlet對象被標記為垃圾回收
-
回收
Servlet由JVM的GC進行垃圾回收

- 第一個到達服務器的 HTTP 請求被委派到 Servlet 容器
- Servlet 容器在調(diào)用 service() 方法之前加載 Servlet
- Servlet 容器處理由多個線程產(chǎn)生的多個請求,每個線程執(zhí)行一個單一的 Servlet 實例的 service() 方法。
Servlet部署
默認情況下,Servlet 應用程序位于路徑 <Tomcat-installation-directory>/webapps/ROOT 下,且類文件放在 <Tomcat-installation-directory>/webapps/ROOT/WEB-INF/classes 中
舉個例子,把aaa.class放入./ROOT/WEB-INF/classes中,并在位于./WEB-INF/下的web.xml中創(chuàng)建如下條目:
<web-app>
<servlet>
<servlet-name>aaa</servlet-name> 當前servlet的名字
<servlet-class>aaa</servlet-name> 對應的aaa.class
</servlet>
<servlet-mapping>
<servlet-name>aaa</servlet-name>
<url-pattern>/AAA</url-pattern> URL(表示需要在輸入的網(wǎng)址的末尾添加/AAA標志特定的URL)
</servlet-mapping>
</web-app>
在aaa.class類之前需要加上@WebServlet("/AAA")
使用Servlet讀取表單數(shù)據(jù)
-
getParameter()
調(diào)用 request.getParameter()來獲取表單參數(shù)的值。
-
getParameterValues()
如果參數(shù)出現(xiàn)一次以上,則調(diào)用該方法,并返回多個值,例如復選框。
-
getParameterNames()
調(diào)用該方法可以得到當前請求中的所有參數(shù)的完整列表
舉個例子:
前端:
<form action="FormTest" method="GET">
名:<input type="text" name="name">
<br />
手機:<input type="text" name="url" />
<input type="submit" value="提交" />
分別輸入:aaa 5656456
經(jīng)get后的URL為:
.../URL?name=aaa&url=5656456
后臺:
使用request.getParameter("name")獲取name
Servlet過濾器
-
使用過濾器的目的:
- 客戶端請求到達時,攔截請求
- 服務器的響應發(fā)回客戶端前,處理響應
過濾器通過Web部署描述符web.xml中的XML標簽來聲明,然后映射到應用程序的部署描述符中的Servlet名稱或URL模式
當Web容器啟動Web應用程序時,它會為web.xml中聲明的每一個過濾器創(chuàng)建一個實例,Filter的執(zhí)行順序與在web.xml配置文件中filter-mapping的配置順序一致,一般把Filter配置在所有的Servlet之前
| seq | 方法&描述 |
|---|---|
| 1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) 該方法完成實際的過濾操作,當客戶端請求方法與過濾器設置匹配的URL時,Servlet容器將先調(diào)用過濾器的doFilter方法。FilterChain用戶訪問后續(xù)過濾器(調(diào)用其doFilter()方法往后傳)。 |
| 2 | public void init(FilterConfig filterConfig) web 應用程序啟動時,web 服務器將創(chuàng)建Filter 的實例對象,并調(diào)用其init方法,讀取web.xml配置,完成對象的初始化功能(filter對象只會創(chuàng)建一次,init方法也只會執(zhí)行一次)。通過init方法的參數(shù),可獲得代表當前filter配置信息的FilterConfig對象。 |
| 3 | public void destroy() Servlet容器在銷毀過濾器實例前調(diào)用該方法,在該方法中釋放Servlet過濾器占用的資源。 |
過濾器是一個實現(xiàn)了 javax.servlet.Filter 接口的 Java 類。javax.servlet.Filter 接口定義了三個方法:
| seq | 方法&描述 |
|---|---|
| 1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) 該方法完成實際的過濾操作,當客戶端請求方法與過濾器設置匹配的URL時,Servlet容器將先調(diào)用過濾器的doFilter方法。FilterChain用戶訪問后續(xù)過濾器(調(diào)用其doFilter()方法往后傳)。 |
| 2 | public void init(FilterConfig filterConfig) web 應用程序啟動時,web 服務器將創(chuàng)建Filter 的實例對象,并調(diào)用其init方法,讀取web.xml配置,完成對象的初始化功能(filter對象只會創(chuàng)建一次,init方法也只會執(zhí)行一次)。通過init方法的參數(shù),可獲得代表當前filter配置信息的FilterConfig對象。 |
| 3 | public void destroy() Servlet容器在銷毀過濾器實例前調(diào)用該方法,在該方法中釋放Servlet過濾器占用的資源。 |
關于使用filterConfig舉個例子
web.xml中:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.kindol.test</filter-class> test為相應的實現(xiàn)Filter接口的類
<init-param>
<param-name>testYo</param-name>
<param-value>abc</param-value>
</init-param>
</filter>
在test類(實現(xiàn)Filter接口)中的init方法:
public void init(FilterConfig filterConfig)
{
String testYo = config.getInitParameter("testYo");
System.out.println("testYo: " + testYo);
}
在整個web.xml中配置如下
<web-app>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.kindol.test</filter-class> test為相應的實現(xiàn)Filter接口的類
<init-param>
<param-name>testYo</param-name>
<param-value>abc</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern> 設置 filter 所攔截的請求路徑,/*表示適合所有Servlet,可以指定特定Servlet路徑(此時將url-pattern改為servlet-name)
<dispatcher>REQUEST</dispatcher> 沒有配置dispatcher就是默認request方式
<dispatcher>FORWARD</dispatcher>
<dispatcher>ERROR</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>myServlet</servlet-name> 類名
<servlet-class>com.kindol.myServlet</servlet-class> 所在的包
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/TomcatTest/myServlet</url-pattern> url對應的所訪問的網(wǎng)址
</servlet-mapping>
</web-app>
web.xml配置各節(jié)點說明
- <filter>指定一個過濾器
- <filter-name>過濾器的名字
- <filter-class>過濾器的完整的限定類名
- <init-param>初始化參數(shù),子元素<param-name>指定參數(shù)的名字,<param-value>指定參數(shù)的值
- </filter>
- <filter-mapping>設置一個 Filter 所負責攔截的資源。一個Filter攔截的資源可通過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑
- <filter-name>設置filter的注冊名稱,該值必須是在<filter>元素中聲明過的過濾器的名字
- <url-pattern>設置 filter 所攔截的請求路徑(過濾器關聯(lián)的URL樣式)
- <servlet-name>指定過濾器所攔截的Servlet名稱(與上面的二選一)
- <dispatcher>指定過濾器所攔截的資源被 Servlet 容器調(diào)用的方式,可以是以下四種方式之一,默認REQUEST。用戶可以設置多個<dispatcher>子元素用來指定 Filter 對資源的多種調(diào)用方式進行攔截
- REQUEST:當用戶直接訪問頁面時,Web容器將會調(diào)用過濾器;若通過如下兩種方法訪問則不調(diào)用此過濾器
- INCLUDE:目標資源是通過RequestDispatcher的include()方法訪問時,那么該過濾器將被調(diào)用
- FORWARD:目標資源是通過RequestDispatcher的forward()方法訪問時,那么該過濾器將被調(diào)用
- ERROR:目標資源是通過聲明式異常處理機制調(diào)用時,那么該過濾器將被調(diào)用
Servlet異常處理(未看)
Servlet Cookie處理
Servlet Cookie 處理需要對中文進行編碼與解碼,方法如下:
String str = java.net.URLEncoder.encode("中文","UTF-8"); //編碼
String str = java.net.URLDecoder.decode("編碼后的字符串","UTF-8"); // 解碼
Cookie通常設置在HTTP頭消息中,比如下方:
HTTP/1.1 200 OK
Date: Fri, 04 Feb 2000 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name=xyz; expires=Friday, 04-Feb-07 22:03:38 GMT;
path=/; domain=runoob.com
Connection: close
Content-Type: text/html
當中,Set-Cookie 頭包含了一個名稱值對、一個GMT日期、一個路徑和一個域。名稱和值會被 URL 編碼。expires 字段是一個指令,告訴瀏覽器在給定的時間和日期之后"忘記"該 Cookie
在瀏覽器這邊,如果瀏覽器被配置為存儲 Cookie,它將會保留此信息直到到期日期。如果用戶的瀏覽器指向任何匹配該 Cookie 的路徑和域的頁面,它會重新發(fā)送 Cookie 到服務器。
Servlet 通過請求方法 request.getCookies() 訪問 Cookie,該方法返回一個 Cookie 對象的數(shù)組
部分Servlet操作Cookie的方法列表
| seq | 方法 & 描述 |
|---|---|
| 1 | public void setDomain(String pattern) 該方法設置 cookie 適用的域,例如 runoob.com。(與之對應的還有getDomain()方法取得cookie適用的域) |
| 2 | public void setMaxAge(int expiry) 該方法設置 cookie 過期的時間(以秒為單位)。如果不這樣設置,cookie 只會在當前 session 會話中持續(xù)有效。(與之對應的還有getMaxAge(),如果返回-1則表示cookie將持續(xù)下去直到瀏覽器關閉) |
| 3 | public String getName() 該方法返回 cookie 的名稱。名稱在創(chuàng)建后不能改變。 |
| 4 | public void setValue(String newValue) 該方法設置與 cookie 關聯(lián)的值。(與之對應的有getValue()獲取與cookie關聯(lián)的值) |
| 5 | public void setPath(String uri) 該方法設置 cookie 適用的路徑。如果不指定路徑,與當前頁面相同目錄下的(包括子目錄下的)所有 URL 都會返回 cookie。 |
| 6 | public void setSecure(boolean flag) 該方法設置cookie表示其是否在加密的(即 SSL)連接上發(fā)送 |
| 7 | public void setComment(String purpose) 設置cookie的注釋。該注釋在瀏覽器向用戶呈現(xiàn) cookie 時非常有用(與之對應的getComment()可以獲得cookie的注釋) |
刪除Cookie:
先獲得所要刪除的cookie(可以通過getName判斷是否為所要的cookie),通過setMaxAge()方法將cookie的年齡設為0,將cookie添加到響應頭
Servlet Session跟蹤
Servlet 提供了 HttpSession 接口,而且,在向客戶端發(fā)送任何文檔內(nèi)容之前調(diào)用 request.getSession()
一些常用方法
使用request.getSession()得到HttpSession對象,當中可以設置參數(shù)true表示如果沒有創(chuàng)建則創(chuàng)建一個HttpSession對象
| seq | 方法 & 描述 |
|---|---|
| 1 | public Object getAttribute(String name) 該方法返回在該 session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null。(對應removeAttribute()刪除指定名稱的對象、setAttribute(String name, Object value)在session綁定一個對象到指定名稱中) |
| 2 | public Enumeration getAttributeNames() 該方法返回 String 對象的枚舉,String 對象包含所有綁定到該 session 會話的對象的名稱。 |
| 3 | public long getCreationTime() 該方法返回該session會話被創(chuàng)建的時間,以毫秒為單位 |
| 4 | public String getId() 該方法返回一個包含分配給該session會話的唯一標識符的字符串。 |
| 5 | public long getLastAccessedTime() 該方法返回客戶端最后一次發(fā)送與該 session 會話相關的請求的時間,以毫秒為單位。 |
| 6 | public int getMaxInactiveInterval() 該方法返回Servlet容器在客戶端訪問時保持 session 會話打開的最大時間間隔,以秒為單位(對應setMaxInactiveInterval(int interval)設置時間)。 |
| 7 | public void invalidate() 該方法指示該session會話無效,并解除綁定到它上面的任何對象 |
| 8 | public boolean isNew() 如果客戶端還不知道該session會話,或者如果客戶選擇不參入該 session 會話,則該方法返回 true |
刪除Session會話數(shù)據(jù):
- 移出特定屬性:removeAttribute(String name)
- 刪除整個session會話:invalidate()
- 設置會話過期時間:setMaxInactiveInterval(int interval)
- web.xml配置(使用Tomcat時)
<session-config>
<session-timeout>15</session-timeout> Tomcat默認為30min,但此處可以覆蓋
</session-config>
Servlet網(wǎng)頁重定向
使用如下方法
public void HttpServletResponse.sendRedirect(String location) throws IOException
也可以通過 setStatus() 和 setHeader() 達到一個效果
String site = "www.a.com";
response.setStatus(response.SC_MOVED_TEMPORARILY);
response.setHeader("Location", site);
原本的URL訪問http://abc.com/本servlet過濾器后,URL會變成www.a.com
Servlet點擊計數(shù)器
步驟如下:
- 在 init() 方法中初始化一個全局變量
- 每次調(diào)用 doGet() 或 doPost() 方法時,都增加全局變量
- 如果需要,使用一個數(shù)據(jù)庫表來存儲全局變量的值在 destroy()中。在下次初始化 Servlet 時,該值可在 init() 方法內(nèi)被讀取
- 如果只想對一個 session 會話計數(shù)一次頁面點擊,那么使用 isNew() 檢查該 session 會話是否已點擊過相同頁面
Servlet自動刷新頁面
比如股票市場等,都需要自動刷新頁面
Servlet中,使用此函數(shù)
public void setIntHeader(String header, int headerValue)
此方法把頭信息 "Refresh" 連同一個表示時間間隔的整數(shù)值headerValue(以秒為單位)發(fā)送回瀏覽器
Servlet包
涉及到 WEB-INF 子目錄的 Web 應用程序結構是所有的 Java web 應用程序的標準,并由 Servlet API 規(guī)范指定。給定一個頂級目錄名 myapp,目錄結構如下所示:
/myapp
/images
/WEB-INF
/classes 包含了所有的Servlet類和其他類文件
/lib
WEB-INF 子目錄中包含應用程序的部署描述符(即web.xml)。所有的 HTML 文件都位于頂級目錄 myapp 下。對于 admin 用戶,會發(fā)現(xiàn) ROOT 目錄是 myApp 的父目錄
WEB-INF/classes 目錄包含了所有的Servlet類和其他類文件,類文件所在的目錄結構與他們的包名稱匹配。例如,如果有一個完全合格的類名稱 com.myorg.MyServlet,那么這個 Servlet 類必須位于以下目錄中:
/myapp/WEB-INF/classes/com/myorg/MyServlet.class
Servlet調(diào)試
- println()
- 消息日志(log4J)
- log()——Servlet API提供的簡單輸出信息的方式,記錄在Servlet容器的日志文件中,例子如下
ServletContext context = getServletContext( );
if (par == null || par.equals(""))
context.log("No message received:",
new IllegalStateException("Missing parameter")); // 通過 Throwable 參數(shù)記錄版本
else
context.log("Here is the visitor's message: " + par);
- 查看原始HTTP請求與相應
- 使用注釋
參考:
Servlet-菜鳥教程