簡介
java servlet:作為一個程序,其運行在web服務器或其他應用服務器上。其充當客戶端請求和服務器上數據庫、應用程序的中間層。(HTTP)。其本身為一個.java文件,編寫一個繼承自HttpServlet的public類。但沒有main。
用處:收集來自網頁表單的用戶輸入;呈現來自數據庫或其他源的記錄;動態創建網頁。
和CGI對比:
性能明顯更好。
Servlet 在 Web 服務器的地址空間內執行。這樣它就沒有必要再創建一個單獨的進程來處理每個客戶端請求。
Servlet 是獨立于平臺的,因為它們是用 Java 編寫的。
服務器上的 Java 安全管理器執行了一系列限制,以保護服務器計算機上的資源。因此,Servlet 是可信的。
Java 類庫的全部功能對 Servlet 來說都是可用的。它可以通過 sockets 和 RMI 機制與 applets、數據庫或其他軟件進行交互。
流程示意圖:
Servlet任務
主要包含:
- 讀取客戶端、瀏覽器發送的顯式的數據。這包擴網頁上的HTML表單。或者來自applet(小程序)、自定義HTTP程序客戶端的表單。
- 讀取客戶端發送的隱式HTTP請求數據。包括數據類型(媒體類型)、壓縮格式、cookies等
- 處理數據并生成結果。在這過程可能需要訪問數據庫,執行RMI(Remote Method Invocatiopn,遠程方法調用)或CORBA調用。(調用Web服務;或者直接計算并得出響應。)
- 發送顯式的數據(文檔格式)到客戶端。文檔格式可包含文本、圖片、excel等。
- 發送隱式的HTTP響應當客戶端。包含:數據的類型、設置緩存參數等。
Servlet 包
創建:
java服務器小程序可以通過javax.servlet和javax.servlet.http包創建。(J2EE的標準組成部分)
運行環境:
其本身屬于java 類,要運行在支持java Servlet解釋器的web服務器上。
運行環境設置
eclipse中servlet運行環境設置
①使用eclipseEE版,或者從SE版升到EE版(通過help/install new... /安裝Web...)
②在eclipse中改變buildPath(SE)
環境配置:https://www.runoob.com/jsp/eclipse-jsp.html
設置 CLASSPATH
http://www.lxweimin.com/p/a3fcd1ec7a17
Servlet生命周期
定義:從創建到毀滅的整個過程。
- 調用init():初始化servlet
- 調用service():處理客戶端請求
- 調用destroy():終止程序。
類所包含函數:
init():
僅在第一次創建Servlet時被調用。后續請求時,已創建所以不需要調用。
何時被調用:用戶第一次請求對應于該Servlet的URL時;或者可以指定Servlet在服務器啟動時就初始化。
service():
執行任務的主要函數。
Servlet的容器(Web服務器)調用service()來處理客戶端的請求,并返回格式化的響應給客戶端。
每次服務器接收到一個Servlet請求,服務器會產生一個新的線程,并調用該函數。
功能:該函數檢查HTTP請求的類型(GET\POST\PUT等),并適時調用doGet、doPost等函數方法。
調用:由容器Web服務器來調用,我們只用重載doGet等函數即可。不用重寫service.
doGet():
參數:HttpServletRequest request、HTTPServletResponse response
request來自于一個URL定位符的正常請求,或者來自于一個未指定METHOD的HTML表單。
doPost:
參數:和doGet一樣
request來自于一個特別指定了METHOD=Post的HTML表單。
destroy():
只會被調用一次,該類(Servlet)生命周期結束時被調用。
功能:關閉數據庫連接、停止后臺線程、把Cookies列表或點擊計數器寫入磁盤、執行其他類似的清理活動。
調用了destroy后,servlet對象被標記為垃圾回收。
架構圖
一個典型的 Servlet 生命周期方案。
- 第一個到達服務器的 HTTP 請求被委派到 Servlet 容器。
- Servlet 容器在調用 service() 方法之前加載 Servlet。
- 然后 Servlet 容器處理由多個線程產生的多個請求,每個線程執行一個單一的 Servlet 實例的 service() 方法。
非IDE開發
當創建一個不依賴集成開發環境如eclipse的Servlet程序時:
①創建一個.java文件:包含類java.io.; javax.servlet. * ; javax.servlet.http.;繼承自HttpServlet;
②對必要函數進行重載:一般為構造函數、doGet、doPost.
③編譯:
- 將所包含的庫,添加到CLASSPATH中。像tomcat的servlet-api.jar的路徑要包含到CLASSPATH中去。
- 將.java文件目錄添加到CLASSPATH中
()*我嘗試了,發現編譯仍不成功。找不到包含的類。
Servlet部署
編譯完,生成.class文件之后,就可以進行部署到web中了。
默認情況:
Servlet的應用程序放在Tomcat/webapps/ROOT/下;
類文件放在.../webapps/ROOT/WEB_INF/classes下;
我們需要將編譯好的.class文件放到web.xml中(位于.../ROOT/WEB_INF/)。如下:如HelloWorld.class文件
<web-app>
<servlet>
<servlet-name>HelloWorld</servlet-name>
<servlet-class>HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorld</servlet-name>
<url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>
</web-app>
Servlet表單數據
信息傳遞:從瀏覽器——web服務器——后臺程序
使用方法:通常位GET、POST。
GET方法
說明:作為從瀏覽器到服務器傳遞的默認方法。
數據載體:URL:頁面地址和參數。中間用 '?' 分隔。如:http://www.test.com/hello?key1=value1&key2=vaue2
大小限制:最多1024個字符。
這些信息使用 QUERY_STRING 頭傳遞,并可以通過 QUERY_STRING 環境變量訪問,Servlet 使用 doGet() 方法處理這種類型的請求
注意:敏感信息,如密碼等,不要使用GET方法傳遞。
POST方法
說明:相比GET,更可靠的傳遞方法。
POST 方法打包信息的方式與 GET 方法基本相同,但是 POST 方法不是把信息作為 URL 中 ? 字符后的文本字符串進行發送,而是把這些信息作為一個單獨的消息。
消息以標準輸出的形式傳到后臺程序,您可以解析和使用這些標準輸出。Servlet 使用 doPost() 方法處理這種類型的請求。
使用Servlet讀取表單數據
根據不同情況,使用不同方法自動解析:
- getParameter():調用:request.getParameter()來獲取表單參數的值。
- getParameterValues():如果參數出現一次以上,則調用該方法,并返回多個值。如:復選框。
- getParameterName():可以得到當前請求中,所有參數的完整列表。
使用URL的GET方法實例
說明:就是在瀏覽器中,URL=(域名)/.../Servlet +"?"+ "para1=String1¶2=String2&..."
如:http://localhost:8080/Test2/Test2/MyServlet2?name=%E5%AD%99%E6%9E%97&url=www.runoob.com
此時參數列表將會以參數request中,傳到doGet中。
可對其進行處理,并用PrintWriter response.getWriter()來進行處理。(如在該頁面輸出)
使用表單的GET方法實例
①建立一個html:hello.html,如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>我的網頁</title>
</head>
<body>
<form action="Test2/MyServlet2" method="GET">
網址名:<input type="text" name="name">
<br />
網址:<input type="text" name="url" />
<input type="submit" value="提交" />
</form>
</body>
</html>
②eclipse中:保存到WebContent/
③當輸入完成,提交時,會調用Myservlet2小程序,并進行輸出。
使用表單的POST方法實例
在Servlet中基本和GET一樣。只是hello.html里面,mothod=“POST”;因為doPost會調用doGet,所以基本一樣。
使用復選框的表單方法實例
方法都和上述類似,建立一個帶有復選框的html,然后可以新建一個servlet來處理。
這需要html的知識。
讀取所有表單參數
使用getParameterName()返回一個enumerate枚舉類型的序列。
然后一一處理。
Servlet客戶端HTTP請求
請求包含:狀態(請求)行,請求頭,請求數據及空行。
Accept | 這個頭信息指定瀏覽器或其他客戶端可以處理的 MIME 類型。值 image/png 或 image/jpeg 是最常見的兩種可能值。 |
---|---|
Accept-Charset | 這個頭信息指定瀏覽器可以用來顯示信息的字符集。例如 ISO-8859-1。 |
Accept-Encoding | 這個頭信息指定瀏覽器知道如何處理的編碼類型。值 gzip 或 compress 是最常見的兩種可能值。 |
Accept-Language | 這個頭信息指定客戶端的首選語言,在這種情況下,Servlet 會產生多種語言的結果。例如,en、en-us、ru 等。 |
Authorization | 這個頭信息用于客戶端在訪問受密碼保護的網頁時識別自己的身份。 |
Connection | 這個頭信息指示客戶端是否可以處理持久 HTTP 連接。持久連接允許客戶端或其他瀏覽器通過單個請求來檢索多個文件。值 Keep-Alive 意味著使用了持續連接。 |
Content-Length | 這個頭信息只適用于 POST 請求,并給出 POST 數據的大小(以字節為單位)。 |
Cookie | 這個頭信息把之前發送到瀏覽器的 cookies 返回到服務器。 |
Host | 這個頭信息指定原始的 URL 中的主機和端口。 |
If-Modified-Since | 這個頭信息表示只有當頁面在指定的日期后已更改時,客戶端想要的頁面。如果沒有新的結果可以使用,服務器會發送一個 304 代碼,表示 Not Modified 頭信息。 |
If-Unmodified-Since | 這個頭信息是 If-Modified-Since 的對立面,它指定只有當文檔早于指定日期時,操作才會成功。 |
Referer | 這個頭信息指示所指向的 Web 頁的 URL。例如,如果您在網頁 1,點擊一個鏈接到網頁 2,當瀏覽器請求網頁 2 時,網頁 1 的 URL 就會包含在 Referer 頭信息中。 |
User-Agent | 這個頭信息識別發出請求的瀏覽器或其他客戶端,并可以向不同類型的瀏覽器返回不同的內容。 |
讀取 HTTP 頭的方法
下面的方法可用在 Servlet 程序中讀取 HTTP 頭。這些方法通過 HttpServletRequest 對象可用。
序號 | 方法 & 描述 |
---|---|
1 | Cookie[] getCookies() 返回一個數組,包含客戶端發送該請求的所有的 Cookie 對象。 |
2 | Enumeration getAttributeNames() 返回一個枚舉,包含提供給該請求可用的屬性名稱。 |
3 | Enumeration getHeaderNames() 返回一個枚舉,包含在該請求中包含的所有的頭名。 |
4 | Enumeration getParameterNames() 返回一個 String 對象的枚舉,包含在該請求中包含的參數的名稱。 |
5 | HttpSession getSession() 返回與該請求關聯的當前 session 會話,或者如果請求沒有 session 會話,則創建一個。 |
6 | HttpSession getSession(boolean create) 返回與該請求關聯的當前 HttpSession,或者如果沒有當前會話,且創建是真的,則返回一個新的 session 會話。 |
7 | Locale getLocale() 基于 Accept-Language 頭,返回客戶端接受內容的首選的區域設置。 |
8 | Object getAttribute(String name) 以對象形式返回已命名屬性的值,如果沒有給定名稱的屬性存在,則返回 null。 |
9 | ServletInputStream getInputStream() 使用 ServletInputStream,以二進制數據形式檢索請求的主體。 |
10 | String getAuthType() 返回用于保護 Servlet 的身份驗證方案的名稱,例如,"BASIC" 或 "SSL",如果JSP沒有受到保護則返回 null。 |
11 | String getCharacterEncoding() 返回請求主體中使用的字符編碼的名稱。 |
12 | String getContentType() 返回請求主體的 MIME 類型,如果不知道類型則返回 null。 |
13 | String getContextPath() 返回指示請求上下文的請求 URI 部分。 |
14 | String getHeader(String name) 以字符串形式返回指定的請求頭的值。 |
15 | String getMethod() 返回請求的 HTTP 方法的名稱,例如,GET、POST 或 PUT。 |
16 | String getParameter(String name) 以字符串形式返回請求參數的值,或者如果參數不存在則返回 null。 |
17 | String getPathInfo() 當請求發出時,返回與客戶端發送的 URL 相關的任何額外的路徑信息。 |
18 | String getProtocol() 返回請求協議的名稱和版本。 |
19 | String getQueryString() 返回包含在路徑后的請求 URL 中的查詢字符串。 |
20 | String getRemoteAddr() 返回發送請求的客戶端的互聯網協議(IP)地址。 |
21 | String getRemoteHost() 返回發送請求的客戶端的完全限定名稱。 |
22 | String getRemoteUser() 如果用戶已通過身份驗證,則返回發出請求的登錄用戶,或者如果用戶未通過身份驗證,則返回 null。 |
23 | String getRequestURI() 從協議名稱直到 HTTP 請求的第一行的查詢字符串中,返回該請求的 URL 的一部分。 |
24 | String getRequestedSessionId() 返回由客戶端指定的 session 會話 ID。 |
25 | String getServletPath() 返回調用 JSP 的請求的 URL 的一部分。 |
26 | String[] getParameterValues(String name) 返回一個字符串對象的數組,包含所有給定的請求參數的值,如果參數不存在則返回 null。 |
27 | boolean isSecure() 返回一個布爾值,指示請求是否使用安全通道,如 HTTPS。 |
28 | int getContentLength() 以字節為單位返回請求主體的長度,并提供輸入流,或者如果長度未知則返回 -1。 |
29 | int getIntHeader(String name) 返回指定的請求頭的值為一個 int 值。 |
30 | int getServerPort() 返回接收到這個請求的端口號。 |
31 | int getParameterMap() 將參數封裝成 Map 類型。 |
實例可以看https://www.runoob.com/servlet/servlet-client-request.html,或者ubuntu里面的eclipse work space
Servlet服務器HTTP響應
響應包含:狀態行、響應頭(報頭)、響應數據(響應正文)、空行。
狀態行:HTTP版本、響應碼、狀態碼對應的簡短信息(用于簡單的闡述。如200 為OK表示正常響應)。
常用響應報頭:
頭信息 | 描述 |
---|---|
Allow | 這個頭信息指定服務器支持的請求方法(GET、POST 等)。 |
Cache-Control | 這個頭信息指定響應文檔在何種情況下可以安全地緩存。可能的值有:public、private 或 no-cache 等。Public 意味著文檔是可緩存,Private 意味著文檔是單個用戶私用文檔,且只能存儲在私有(非共享)緩存中,no-cache 意味著文檔不應被緩存。 |
Connection | 這個頭信息指示瀏覽器是否使用持久 HTTP 連接。值 close 指示瀏覽器不使用持久 HTTP 連接,值 keep-alive 意味著使用持久連接。 |
Content-Disposition | 這個頭信息可以讓您請求瀏覽器要求用戶以給定名稱的文件把響應保存到磁盤。 |
Content-Encoding | 在傳輸過程中,這個頭信息指定頁面的編碼方式。 |
Content-Language | 這個頭信息表示文檔編寫所使用的語言。例如,en、en-us、ru 等。 |
Content-Length | 這個頭信息指示響應中的字節數。只有當瀏覽器使用持久(keep-alive)HTTP 連接時才需要這些信息。 |
Content-Type | 這個頭信息提供了響應文檔的 MIME(Multipurpose Internet Mail Extension)類型。 |
Expires | 這個頭信息指定內容過期的時間,在這之后內容不再被緩存。 |
Last-Modified | 這個頭信息指示文檔的最后修改時間。然后,客戶端可以緩存文件,并在以后的請求中通過 If-Modified-Since 請求頭信息提供一個日期。 |
Location | 這個頭信息應被包含在所有的帶有狀態碼的響應中。在 300s 內,這會通知瀏覽器文檔的地址。瀏覽器會自動重新連接到這個位置,并獲取新的文檔。 |
Refresh | 這個頭信息指定瀏覽器應該如何盡快請求更新的頁面。您可以指定頁面刷新的秒數。 |
Retry-After | 這個頭信息可以與 503(Service Unavailable 服務不可用)響應配合使用,這會告訴客戶端多久就可以重復它的請求。 |
Set-Cookie | 這個頭信息指定一個與頁面關聯的 cookie。 |
設置 HTTP 響應報頭的方法
下面的方法可用于在 Servlet 程序中設置 HTTP 響應報頭。這些方法通過 HttpServletResponse 對象可用。
如:response.setIntHeader("Refresh",value); 可以設置每value秒,自動刷新頁面
序號 | 方法 & 描述 |
---|---|
1 | String encodeRedirectURL(String url) 為 sendRedirect 方法中使用的指定的 URL 進行編碼,或者如果編碼不是必需的,則返回 URL 未改變。 |
2 | String encodeURL(String url) 對包含 session 會話 ID 的指定 URL 進行編碼,或者如果編碼不是必需的,則返回 URL 未改變。 |
3 | boolean containsHeader(String name) 返回一個布爾值,指示是否已經設置已命名的響應報頭。 |
4 | boolean isCommitted() 返回一個布爾值,指示響應是否已經提交。 |
5 | void addCookie(Cookie cookie) 把指定的 cookie 添加到響應。 |
6 | void addDateHeader(String name, long date) 添加一個帶有給定的名稱和日期值的響應報頭。 |
7 | void addHeader(String name, String value) 添加一個帶有給定的名稱和值的響應報頭。 |
8 | void addIntHeader(String name, int value) 添加一個帶有給定的名稱和整數值的響應報頭。 |
9 | void flushBuffer() 強制任何在緩沖區中的內容被寫入到客戶端。 |
10 | void reset() 清除緩沖區中存在的任何數據,包括狀態碼和頭。 |
11 | void resetBuffer() 清除響應中基礎緩沖區的內容,不清除狀態碼和頭。 |
12 | void sendError(int sc) 使用指定的狀態碼發送錯誤響應到客戶端,并清除緩沖區。 |
13 | void sendError(int sc, String msg) 使用指定的狀態發送錯誤響應到客戶端。 |
14 | void sendRedirect(String location) 使用指定的重定向位置 URL 發送臨時重定向響應到客戶端。 |
15 | void setBufferSize(int size) 為響應主體設置首選的緩沖區大小。 |
16 | void setCharacterEncoding(String charset) 設置被發送到客戶端的響應的字符編碼(MIME 字符集)例如,UTF-8。 |
17 | void setContentLength(int len) 設置在 HTTP Servlet 響應中的內容主體的長度,該方法設置 HTTP Content-Length 頭。 |
18 | void setContentType(String type) 如果響應還未被提交,設置被發送到客戶端的響應的內容類型。 |
19 | void setDateHeader(String name, long date) 設置一個帶有給定的名稱和日期值的響應報頭。 |
20 | void setHeader(String name, String value) 設置一個帶有給定的名稱和值的響應報頭。 |
21 | void setIntHeader(String name, int value) 設置一個帶有給定的名稱和整數值的響應報頭。 |
22 | void setLocale(Locale loc) 如果響應還未被提交,設置響應的區域。 |
23 | void setStatus(int sc) 為該響應設置狀態碼。 |
Servlet HTTP狀態碼
HTTP請求和響應的消息格式是類似的:
- 狀態行+回車換行符(回車+換行)
- 0或多個標題行(表明數據的某些狀態或格式)+回車換行符
- 空白行(即回車換行符)
- 可選的消息主體。(如文件、查詢數據、查詢輸出等)
如:
HTTP/1.1 200 OK
Content-Type: text/html
Header2: ...
...
HeaderN: ...
(Blank Line)
<!doctype ...>
<html>
<head>...</head>
<body>
...
</body>
</html>
具體狀態碼可以在HTTP.md中查看,這里只寫出主要類型。
分類 | 分類描述 |
---|---|
1** | 信息,服務器收到請求,需要請求者繼續執行操作 |
2** | 成功,操作被成功接收并處理 |
3** | 重定向,需要進一步的操作以完成請求 |
4** | 客戶端錯誤,請求包含語法錯誤或無法完成請求 |
5** | 服務器錯誤,服務器在處理請求的過程中發生了錯誤 |
設置HTTP狀態碼的方法
通過doGet中的response參數進行設置。(HttpServletResponse)
如:response.setStatus(int statusCode);
序號 | 方法 & 描述 |
---|---|
1 | public void setStatus ( int statusCode ) 該方法設置一個任意的狀態碼。setStatus 方法接受一個 int(狀態碼)作為參數。如果您的響應包含了一個特殊的狀態碼和文檔,請確保在使用 PrintWriter 實際返回任何內容之前調用 setStatus。 |
2 | public void sendRedirect(String url) 該方法生成一個 302 響應,連同一個帶有新文檔 URL 的 Location 頭。 |
3 | public void sendError(int code, String message) 該方法發送一個狀態碼(通常為 404),連同一個在 HTML 文檔內部自動格式化并發送到客戶端的短消息。 |
Servlet過濾器Filter
用處:過濾器用來攔截請求或響應。并將自身及過濾器鏈執行完畢后,再執行相應請求或響應。
可以將一個或多個 Servlet 過濾器附加到一個 Servlet 或一組 Servlet。Servlet 過濾器也可以附加到 JavaServer Pages (JSP) 文件和 HTML 頁面。調用 Servlet 前調用所有附加的 Servlet 過濾器。
Servlet 過濾器是可用于 Servlet 編程的 Java 類,可以實現以下目的:
- 在客戶端的請求訪問后端資源之前,攔截這些請求。
- 在服務器的響應發送回客戶端之前,處理這些響應。
根據規范建議的各種類型的過濾器:
- 身份驗證過濾器(Authentication Filters)。
- 數據壓縮過濾器(Data compression Filters)。
- 加密過濾器(Encryption Filters)。
- 觸發資源訪問事件過濾器。
- 圖像轉換過濾器(Image Conversion Filters)。
- 日志記錄和審核過濾器(Logging and Auditing Filters)。
- MIME-TYPE 鏈過濾器(MIME-TYPE Chain Filters)。
- 標記化過濾器(Tokenizing Filters)。
- XSL/T 過濾器(XSL/T Filters),轉換 XML 內容。
說明:在servlet 3.0后,可以不在web.xml中進行聲明,可直接在Filter.java中,在@webFilter里面,進行聲明。
過濾器類函數:
序號 | 方法 & 描述 |
---|---|
1 | public void doFilter (ServletRequest, ServletResponse, FilterChain) 該方法完成實際的過濾操作,當客戶端請求方法與過濾器設置匹配的URL時,Servlet容器將先調用過濾器的doFilter方法。FilterChain用戶訪問后續過濾器。 |
2 | public void init(FilterConfig filterConfig) web 應用程序啟動時,web 服務器將創建Filter 的實例對象,并調用其init方法,讀取web.xml配置,完成對象的初始化功能,從而為后續的用戶請求作好攔截的準備工作(filter對象只會創建一次,init方法也只會執行一次)。開發人員通過init方法的參數,可獲得代表當前filter配置信息的FilterConfig對象。 |
3 | public void destroy() Servlet容器在銷毀過濾器實例前調用該方法,在該方法中釋放Servlet過濾器占用的資源。 |
針對2中的config,其配置信息可以在@WebFilter中設置。
@WebFilter常用屬性:
屬性 | 類型 | 是否 必需 | 說明 |
---|---|---|---|
asyncSupported | boolean | 否 | 指定Filter是否支持異步模式 |
dispatcherTypes | DispatcherType[] | 否 | 指定Filter對哪種方式的請求進行過濾。支持的屬性:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST;默認過濾所有方式的請求 |
filterName | String | 否 | Filter名稱 |
initParams | WebInitParam[] | 否 | 配置參數 |
displayName | String | 否 | Filter顯示名 |
servletNames | String[] | 否 | 指定對哪些Servlet進行過濾 |
urlPatterns/value | String[] | 否 | 兩個屬性作用相同,指定攔截的路徑 |
示例:
@WebFilter(filterName = "loginFilter",
urlPatterns = "/*",
initParams = {
@WebInitParam(name = "loginUI", value = "/home/loginUI"),
@WebInitParam(name = "loginProcess", value = "home/login"),
@WebInitParam(name = "encoding", value = "utf-8")
})
如想要設置該過濾器針對所有servlet,可以設置urlPatterns=“/*”即可。
還有一種方法:web.xml中配置,必須要在servlet配置之前:
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>cn.edu.njit.filter.LoginFilter</filter-class>
<init-param>
<param-name>loginUI</param-name>
<param-value>/home/loginUI</param-value>
</init-param>
<init-param>
<param-name>loginProcess</param-name>
<param-value>home/login</param-value>
</init-param>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
過濾器的順序(應用中)
如果在web.xml中,調整<filter-mapping>的先后順序可以控制過濾器的先后順序。
web.xml配置各節點說明
- <filter>指定一個過濾器。
- <filter-name>用于為過濾器指定一個名字,該元素的內容不能為空。
- <filter-class>元素用于指定過濾器的完整的限定類名。
- <init-para>元素用于為過濾器指定初始化參數,它的子元素<param-name>指定參數的名字,<param-value>指定參數的值。
- 在過濾器中,可以使用
FilterConfig
接口對象來訪問初始化參數。
- 在過濾器中,可以使用
- <filter-mapping>元素用于設置一個 Filter 所負責攔截的資源。一個Filter攔截的資源可通過兩種方式來指定:Servlet 名稱和資源訪問的請求路徑
- <filter-name>子元素用于設置filter的注冊名稱。該值必須是在<filter>元素中聲明過的過濾器的名字
- <url-pattern>設置 filter 所攔截的請求路徑(過濾器關聯的URL樣式)
- <servlet-name>指定過濾器所攔截的Servlet名稱。
- <dispathcer>(調度員)指定過濾器所攔截的資源被 Servlet 容器調用的方式,可以是 REQUEST , INCLUDE , FORWARD 和 ERROR之一,默認REQUEST。用戶可以設置多個<dispathcer>子元素用來指定 Filter 對資源的多種調用方式進行攔截。
- <dispatcher>子元素可以設置的值及其意義
-
REQUEST
:當用戶直接訪問頁面時,Web容器將會調用過濾器。如果目標資源是通過RequestDispatcher的include()或forward()方法訪問時,那么該過濾器就不會被調用。 -
INCLUDE
:如果目標資源是通過RequestDispatcher的include()方法訪問時,那么該過濾器將被調用。除此之外,該過濾器不會被調用。
-
-
FORWARD
:如果目標資源是通過RequestDispatcher的forward()方法訪問時,那么該過濾器將被調用,除此之外,該過濾器不會被調用。-
ERROR
:如果目標資源是通過聲明式異常處理機制調用時,那么該過濾器將被調用。除此之外,過濾器不會被調用。
-
Servlet異常處理
說明:當拋出異常時,可以用異常處理程序進行處理。只可以處理自己編寫的servlet等程序,如果客戶在瀏覽器中輸入了服務器主機+端口+任意號,是不會調用的。
聲明:
可以在web.xml中,進行聲明,格式如下:
<!-- error-code 相關的錯誤頁面 -->
<error-page>
<error-code>404</error-code>
<location>/ErrorHandler</location>
</error-page>
<!-- exception-type 相關的錯誤頁面 -->
<error-page>
<exception-type>
javax.servlet.ServletException
</exception-type >
<location>/ErrorHandler</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/ErrorHandler0</location>
</error-page>
上述異常程序ErrorHandler0可以處理所有異常,因為異常都是實現Throwable的類。
異常處理類的具體實現:與servlet、Filter都類似。都是繼承自HttpServlet類。
實現要素:
①通過request得到:具體異常Throwable、異常號status_code、異常的servlet名字 servlet_name、異常的uri(統一資源標識符)request_uri;
②設置response格式及字符集,并設置建立一個輸出對象。
③輸出一個html來應答。
下面是關于上面的 web.xml 異常處理要注意的點:
- Servlet ErrorHandler 與其他的 Servlet 的定義方式一樣,且在 web.xml 中進行配置。
- 如果有錯誤狀態代碼出現,不管為 404(Not Found 未找到)或 403(Forbidden 禁止),則會調用 ErrorHandler 的 Servlet。
- 如果 Web 應用程序拋出 ServletException 或 IOException,那么 Web 容器會調用 ErrorHandler 的 Servlet。
- 您可以定義不同的錯誤處理程序來處理不同類型的錯誤或異常。上面的實例是非常通用的,希望您能通過實例理解基本的概念。
請求屬性 - 錯誤/異常
以下是錯誤處理的 Servlet 可以訪問的請求屬性列表,用來分析錯誤/異常的性質。
序號 | 屬性 & 描述 |
---|---|
1 | javax.servlet.error.status_code 該屬性給出狀態碼,狀態碼可被存儲,并在存儲為 java.lang.Integer 數據類型后可被分析。 |
2 | javax.servlet.error.exception_type 該屬性給出異常類型的信息,異常類型可被存儲,并在存儲為 java.lang.Class 數據類型后可被分析。 |
3 | javax.servlet.error.message 該屬性給出確切錯誤消息的信息,信息可被存儲,并在存儲為 java.lang.String 數據類型后可被分析。 |
4 | javax.servlet.error.request_uri 該屬性給出有關 URL 調用 Servlet 的信息,信息可被存儲,并在存儲為 java.lang.String 數據類型后可被分析。 |
5 | javax.servlet.error.exception 該屬性給出異常產生的信息,信息可被存儲,并在存儲為 java.lang.Throwable 數據類型后可被分析。 |
6 | javax.servlet.error.servlet_name 該屬性給出 Servlet 的名稱,名稱可被存儲,并在存儲為 java.lang.String 數據類型后可被分析。 |
Servlet Cookie處理
Cookie是存儲在計算機上的本文文件,并保留了各種跟蹤信息。
步驟:
服務器腳本向瀏覽器發送一組Cookie,如:賬號、密碼、識別號等。
瀏覽器將這些信息儲存在本地計算機上,備用。
當再次訪問之前的服務器時,無論任何請求URL,都會把Cookie發送到服務器,服務器使用這些信息來識別用戶。
Servlet Cookie 處理需要對中文進行編碼與解碼,方法如下:
String str = java.net.URLEncoder.encode("中文","UTF-8"); //編碼
String str = java.net.URLDecoder.decode("編碼后的字符串","UTF-8"); // 解碼
通常Cookie由HTTP頭來傳輸。(雖然 JavaScript 也可以直接在瀏覽器上設置一個 Cookie)
如下是服務器中,設置了Cookie的servlet會發送的響應頭信息:
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
Cookie包含:一個名稱值對、一個GMT日期(expires,到期,期限)、一個路徑、一個域名。
expires告訴瀏覽器在此日期后忘記Cookie
如果設置瀏覽器為儲存Cookie,就會保存這些信息,直到到期日期。當用戶通過此瀏覽器訪問與Cookie中域名、路勁相匹配的頁面時,就會發送此Cookie到服務器。
此時的HTTP請求頭信息可能為:
GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.6 (X11; I; Linux 2.2.6-15apmac ppc)
Host: zink.demon.co.uk:1126
Accept: image/gif, */*
Accept-Encoding: gzip
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Cookie: name=xyz
而此時服務器的Servlet就可以通過Cookie[] request.getCookies()來訪問Cookie。
Servlet Cookie 函數(方法)
以下是在 Servlet 中操作 Cookie 時可使用的有用的方法列表。
序號 | 方法 & 描述 |
---|---|
1 | public void setDomain(String pattern) 該方法設置 cookie 適用的域,例如 runoob.com。 |
2 | public String getDomain() 該方法獲取 cookie 適用的域,例如 runoob.com。 |
3 | public void setMaxAge(int expiry) 該方法設置 cookie 過期的時間(以秒為單位)。如果不這樣設置,cookie 只會在當前 session 會話中持續有效。 |
4 | public int getMaxAge() 該方法返回 cookie 的最大生存周期(以秒為單位),默認情況下,-1 表示 cookie 將持續下去,直到瀏覽器關閉。 |
5 | public String getName() 該方法返回 cookie 的名稱。名稱在創建后不能改變。 |
6 | public void setValue(String newValue) 該方法設置與 cookie 關聯的值。 |
7 | public String getValue() 該方法獲取與 cookie 關聯的值。 |
8 | public void setPath(String uri) 該方法設置 cookie 適用的路徑。如果您不指定路徑,與當前頁面相同目錄下的(包括子目錄下的)所有 URL 都會返回 cookie。 |
9 | public String getPath() 該方法獲取 cookie 適用的路徑。 |
10 | public void setSecure(boolean flag) 該方法設置布爾值,表示 cookie 是否應該只在加密的(即 SSL)連接上發送。 |
11 | public void setComment(String purpose) 設置cookie的注釋。該注釋在瀏覽器向用戶呈現 cookie 時非常有用。 |
12 | public String getComment() 獲取 cookie 的注釋,如果 cookie 沒有注釋則返回 null。 |
設置步驟:
通過servlet設置Cookie的步驟包括:
①創建一個Cookie對象:構造函數參數可以傳入cookie的名稱和值。
Cookie cookie = new Cookie("key","value");
這兩個字符串不能包含這些字符:[] () = , '' / ? @ : ;
②設置最大生存周期:使用cookie.setMaxAge()來指定保持有效的時間(秒為單位)。
cookie.setMaxAge(60*60*24*7); //保存七天
③發送Cookie到HTTP響應頭:用response.addCookie來添加
response.addCookie(cookie);
實例:https://www.runoob.com/servlet/servlet-cookies-handling.html
通過Servlet讀取Cookie
在servlet:doGet中調用Cookie[] request.getCookies() (java.servlet.http.Cookie),然后遍歷數組,進行處理。
實例:https://www.runoob.com/servlet/servlet-cookies-handling.html
通過servlet刪除Cookie
步驟:
①讀取一個cookie = request.getCookies[x];
②設置其最大年齡為0:cookie.setMaxAge(0);
③response.addCookie(cookie);
Servlet Session跟蹤
session會話,大概表示指定瀏覽器和服務器之間發生過的會議信息。即類似于Cookie。
HTTP是一種“無狀態"協議,每次客戶端檢索網頁時,打開一個單獨的連接,到服務器。服務器不保存之前客戶端請求的任何記錄。
用三種方法來維護客戶端和服務器之間的session:
-
Cookie:
服務器可以分配一個唯一的session ID作為標識唯一Web瀏覽器客戶端的cookie。客戶端再次請求時,可以根據接收到的cookie來識別該客戶端。
ps:不是很有效,因為有的瀏覽器不支持cookie,不建議使用。
-
隱藏的表單字段
服務器servlet可以發送一個隱藏的HTML表單字段,以及一個唯一的session ID,如下:
<input type="hide" name="sessionid" value="12345">
該條目意味著,當表單被提交時,指定的名稱和值會被自動包含在 GET 或 POST 數據中。每次當 Web 瀏覽器發送回請求時,session_id 值可以用于保持不同的 Web 瀏覽器的跟蹤。
這可能是一種保持 session 會話跟蹤的有效方式,但是點擊常規的超文本鏈接(<A HREF...>)不會導致表單提交,因此隱藏的表單字段也不支持常規的 session 會話跟蹤。
-
URL重寫
在每個URL末尾追加一些額外的數據來標識session會話。服務器會把該session會話標識符與一組有關的會話數據相關聯。
例如:http://w3cschool.cc/file.html;sessionid=12345
session會話標識符會被附加為sessionid=12345,web服務器可以訪問其,來識別客戶端。
URL 重寫是一種更好的維持 session 會話的方式,它在瀏覽器不支持 cookie 時能夠很好地工作,但是它的缺點是會動態生成每個 URL 來為頁面分配一個 session 會話 ID,即使是在很簡單的靜態 HTML 頁面中也會如此。
HTTPSession對象
除上三種外,servlet提供了HttpSession接口,提供一種跨多個頁面請求或訪問網站時,識別用戶及其相關數據的方式。
HttpSession session = request.getSession();
要在servlet中發送任何文檔內容之前,調用request.getSession().
下面是HttpSession接口的重要函數:
序號 | 方法 & 描述 |
---|---|
1 | public Object getAttribute(String name) 該方法返回在該 session 會話中具有指定名稱的對象,如果沒有指定名稱的對象,則返回 null。 |
2 | public Enumeration getAttributeNames() 該方法返回 String 對象的枚舉,String 對象包含所有綁定到該 session 會話的對象的名稱。 |
3 | public long getCreationTime() 該方法返回該 session 會話被創建的時間,自格林尼治標準時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。 |
4 | public String getId() 該方法返回一個包含分配給該 session 會話的唯一標識符的字符串。 |
5 | public long getLastAccessedTime() 該方法返回客戶端最后一次發送與該 session 會話相關的請求的時間自格林尼治標準時間 1970 年 1 月 1 日午夜算起,以毫秒為單位。 |
6 | public int getMaxInactiveInterval() 該方法返回 Servlet 容器在客戶端訪問時保持 session 會話打開的最大時間間隔,以秒為單位。 |
7 | public void invalidate() 該方法指示該 session 會話無效,并解除綁定到它上面的任何對象。 |
8 | public boolean isNew() 如果客戶端還不知道該 session 會話,或者如果客戶選擇不參入該 session 會話,則該方法返回 true。 |
9 | public void removeAttribute(String name) 該方法將從該 session 會話移除指定名稱的對象。 |
10 | public void setAttribute(String name, Object value) 該方法使用指定的名稱綁定一個對象到該 session 會話。 |
11 | public void setMaxInactiveInterval(int interval) 該方法在 Servlet 容器指示該 session 會話無效之前,指定客戶端請求之間的時間,以秒為單位。 |
實例可以看https://www.runoob.com/servlet/servlet-session-tracking.html
刪除 Session 會話數據
當您完成了一個用戶的 session 會話數據,您有以下幾種選擇:
- 移除一個特定的屬性:您可以調用 public void removeAttribute(String name) 方法來刪除與特定的鍵相關聯的值。
- 刪除整個 session 會話:您可以調用 public void invalidate() 方法來丟棄整個 session 會話。
- 設置 session 會話過期時間:您可以調用 public void setMaxInactiveInterval(int interval) 方法來單獨設置 session 會話超時。
- 注銷用戶:如果使用的是支持 servlet 2.4 的服務器,您可以調用 logout 來注銷 Web 服務器的客戶端,并把屬于所有用戶的所有 session 會話設置為無效。
- web.xml 配置:如果您使用的是 Tomcat,除了上述方法,您還可以在 web.xml 文件中配置 session 會話超時,如下所示:
<session-config>
<session-timeout>15</session-timeout>
</session-config>
上面實例中的超時時間是以分鐘為單位,將覆蓋 Tomcat 中默認的 30 分鐘超時時間。
在一個 Servlet 中的 getMaxInactiveInterval() 方法會返回 session 會話的超時時間,以秒為單位。所以,如果在 web.xml 中配置 session 會話超時時間為 15 分鐘,那么 getMaxInactiveInterval() 會返回 900。
數據庫的連接
這節暫時沒學數據庫,等學了再回來學。
文件上傳
步驟:
①建立一個Upload.jsp:用html form標簽提供瀏覽器頁面上傳渠道,和提交按鈕。
②建立一個servlet:來進行文件處理,如保存文件,傳遞消息給③中文件。
③建立一個ShowResult.jsp:接收servlet中信息,并顯示反饋給瀏覽器。
Upload.jsp:
要點說明:
<form action="UploadServlet" method="post" enctype="multipart/form-data"/>
- method只能為POST
- enctype要是多媒體格式
- 多個文件上傳時,要使用多個<input ... />標簽。
UploadServlet.java:
要點說明:
可以沒有doGet,代碼必須寫在doPost中
-
使用類:
DiskFileItemFactory類:配置上傳文件項目的內存臨界值、臨時存放目錄等。
ServletFileUpload upload = new ...(factory):servlet文件上傳類,配置上傳的屬性:文件最大字節數、包含表單的最大字節數、字節編碼等。
FileItem:來接收解析的文件項目。 = upload.parseRequest(new ServletRequestContext(request));
File:建立一個文件來接收FileItem。
將成功或錯誤信息交給ShowResult.jsp:request.getServletContext().getRequestDispatcher("/Showresult.jsp").forward(request,response);
實例:https://www.runoob.com/servlet/servlet-file-uploading.html或者ubuntu eclipse/workspace/Upload.jsp...
ShowResult:
一張html,將收到的message發送給瀏覽器。
body里面放入這個即可:
<center>
<h2>${message}</h2>
</center>
servlet處理日期
Date類
-
SimpleDateFormat類
使用保留ASICC碼來識別年月日時等
字符 描述 實例
G Era 指示器 AD
y 四位數表示的年 2001
M 一年中的月 July 或 07
d 一月中的第幾天 10
h 帶有 A.M./P.M. 的小時(1~12) 12
H 一天中的第幾小時(0~23) 22
m 一小時中的第幾分 30
s 一分中的第幾秒 55
S 毫秒 234
E 一周中的星期幾 Tuesday
D 一年中的第幾天 360
F 所在的周是這個月的第幾周 2 (second Wed. in July)
w 一年中的第幾周 40
W 一月中的第幾周 1
a A.M./P.M. 標記 PM
k 一天中的第幾小時(1~24) 24
K 帶有 A.M./P.M. 的小時(0~11) 10
z 時區 Eastern Standard Time
' Escape for text Delimiter
" 單引號 `
網頁重定向
方法:
①response.sendRedirect(String location),就可以重定向。
②Servlet通過設置狀態碼和響應頭,返回給瀏覽器,隨后瀏覽器訪問重定向后的頁面。
...
String site = "http://www.baidu.com";
response.setStatus(response.SC_MOVED_TEMPORARILY); //臨時地移動
response.setHeader("Location",site);
...
說明:site:如果不加http://則默認為當前目錄下的地址。
網頁點擊量
簡單實現:
①創建全局成員變量int hitCount;
②每次doGet、doPost自增。
拓展:如果需要在服務器重啟后能續接上,則可以在銷毀destroy時,將其放入數據庫,初始化時,將其從庫中取出。(或者存在文件中,切記:文件寫入流會清空文件,需要在讀取后再建立。)
整個網站的點擊量,可以利用過濾器。
自動刷新時間:通過response,將頭信息傳回給瀏覽器:
response.setIntHeader("Refresh","5");每5秒刷新一次