Servlet基礎

現(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進行垃圾回收

Servlet-LifeCycle.jpg
  • 第一個到達服務器的 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過濾器

  • 使用過濾器的目的:

    1. 客戶端請求到達時,攔截請求
    2. 服務器的響應發(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-菜鳥教程
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 本文包括:1、Filter簡介2、Filter是如何實現(xiàn)攔截的?3、Filter開發(fā)入門4、Filter的生命周期...
    廖少少閱讀 7,522評論 3 56
  • 這部分主要是與Java Web和Web Service相關的面試題。 96、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,502評論 0 10
  • “僅以此片獻給最珍貴的你”最后一句話已經(jīng)出現(xiàn)在大屏幕了,可是所有的人都還是不舍得走,直到整個屏幕黑下來,才緩緩擦去...
    恣岑呀閱讀 1,491評論 3 9
  • 人就是這么賤,在的時候嫌嘮叨,不在的時候又想念。 今天老爸出遠門,清明回去的時候老爸說這說那,總覺得煩??墒撬F(xiàn)在...
    傻小子97閱讀 236評論 0 0

友情鏈接更多精彩內(nèi)容