圖解 深入淺出 JavaWeb:Servlet 再說幾句

Writer????? :BYSocket(泥沙磚瓦漿木匠)

微???????? 博:BYSocket

豆???????? 瓣:BYSocket

FaceBook:BYSocket

Twitter??? :BYSocket

上一篇的《?Servlet必會必知?》受到大家一致好評 — (感謝?讀者 及 OSC 推薦 每日一’搏’)image

后來覺得還有些東西沒點到,這邊補充補充。

一、回到 HttpServlet 的 service方法

Servlet 基礎接口定義了用于客戶端請求處理的service方法。 當請求到達Servlet容器,由Servlet容器路由到一個Servlet實例

比如說?javax.servlet.http.HttpServlet?類 ,其中有一個?protected?void service 方法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
private static final String HEADER_IFMODSINCE = "If-Modified-Since";
private static final String LSTRING_FILE =
????????"javax.servlet.http.LocalStrings";
private static ResourceBundle lStrings =
????????ResourceBundle.getBundle(LSTRING_FILE);
/**
?* HTTP狀態碼304
?*/
public static final int SC_NOT_MODIFIED = 304;
/**
?* 接收來自 public service方法的標準HTTP請求,
?* 并將它們分發給此類中定義的doXXX方法。
?*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
????????throws ServletException, IOException {
????// 獲取請求方法名
????String method = req.getMethod();
????// 如果是GET請求
????if (method.equals(METHOD_GET)) {
????????// 上一次修改HttpServletRequest對象的時間
????????long lastModified = getLastModified(req);
????????// 沒有改變
????????if (lastModified == -1) {
????????????doGet(req, resp);
????????} else {
????????????long ifModifiedSince;
????????????try {
????????????????// 獲取請求頭中服務器修改時間
????????????????ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
????????????} catch (IllegalArgumentException iae) {
????????????????// 獲取無效
????????????????ifModifiedSince = -1;
????????????}
????????????// 如果請求頭服務器修改時間遲
????????????if (ifModifiedSince < (lastModified / 1000 * 1000)) {
????????????????// 設置修改HttpServletResponse對象的時間,重新設置瀏覽器的參數
??????????????????????????????//maybeSetLastModified(resp, lastModified);
????????????????// 調用doGet方法
????????????????????????????????doGet(req, resp);
????????????} else {
????????????????// 304 HTTP狀態碼
????????????????resp.setStatus(SC_NOT_MODIFIED);
????????????}
????????}
????} else if (method.equals(METHOD_HEAD)) {
????????long lastModified = getLastModified(req);
??????//maybeSetLastModified(resp, lastModified);
????????doHead(req, resp);
????} else if (method.equals(METHOD_POST)) {
????????doPost(req, resp);
????} else if (method.equals(METHOD_PUT)) {
????????doPut(req, resp);
????} else if (method.equals(METHOD_DELETE)) {
????????doDelete(req, resp);
????} else if (method.equals(METHOD_OPTIONS)) {
????????doOptions(req,resp);
????} else if (method.equals(METHOD_TRACE)) {
????????doTrace(req,resp);
????} else {
????????// 如果沒有被請求到的話
????????String errMsg = lStrings.getString("http.method_not_implemented");
????????Object[] errArgs = new Object[1];
????????errArgs[0] = method;
????????errMsg = MessageFormat.format(errMsg, errArgs);
????????// 501 HTTP狀態碼
????????resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
????}
}

代碼邏輯詳解如下:

1、HttpServlet的?protected?void service方法 用于接受?public?service接收的標準HTTP請求

也就是說,HttpServlet?重寫了父類?GenericServlet?的?service方法。如圖顯示的是該方法,將從容器獲取的?ServletRequest?和?ServletResponse?對象強制轉化成 用于HTTP處理的HttpServletRequest?和?HttpServletResponse?對象。然后將兩個對象路由給了?HttpServlet的?protected?void service方法(圖中代碼選中處)

?

image

2、然后根據請求的方法名,分發到此類定義的doXXX方法。如果沒有被請求到的話,則返回501?HTTP 狀態碼。

這樣子仿佛明白了什么,也就是說,如果你在?HelloServlet重寫doGet方法,這里分發到就是HttpServlet的子類HelloServlet的doGet方法。

哦~ 還有,501 HTTP 狀態碼?—?未實現(Not implemented)表示服務器不支持實現請求所需要的功能。例如,客戶發出了一個服務器不支持的PUT請求。原來如此,所謂死記硬背這些HTTP 狀態碼有什么用?這樣的記憶才是最有效的。

休息休息,小廣告插一下 :(維持生計,O(∩_∩)O~)

涉及到的代碼都會在開源項目?servlet-core-learning?。簡介?— Servlet/JSP學習積累的例子,是Java EE初學者及Servlet/JSP核心技術鞏固的最佳實踐

大致就是這兩步驟。這就是service的工作流程

1、接受 public service接收的標準HTTP請求。

2、分發到定義的doXXX方法

二、GET 請求的處理詳解

上面對于GET請求代碼處理如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 如果是GET請求
if (method.equals(METHOD_GET)) {
????// 上一次修改HttpServletRequest對象的時間
????long lastModified = getLastModified(req);
????// 沒有改變
????if (lastModified == -1) {
????????doGet(req, resp);
????} else {
????????long ifModifiedSince;
????????try {
????????????// 獲取請求頭中服務器修改時間
????????????ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
????????} catch (IllegalArgumentException iae) {
????????????// 獲取無效
????????????ifModifiedSince = -1;
????????}
????????// 如果請求頭服務器修改時間遲
????????if (ifModifiedSince < (lastModified / 1000 * 1000)) {
????????????// 設置修改HttpServletResponse對象的時間,重新設置瀏覽器的參數
??????????//maybeSetLastModified(resp, lastModified);
????????????// 調用doGet方法
????????????doGet(req, resp);
????????} else {
????????????// 304 HTTP狀態碼
????????????resp.setStatus(SC_NOT_MODIFIED);
????????}
????}
}

這里,

1、定義了?getLastModified(req) 方法。用于獲取上一次修改HttpServletRequest對象的時間。如果lastModified為默認的?–1L,則總是刷新

這個getLastModified,是HttpServlet定義了用于支持有條件GET操作。即當客戶端通過GET請求獲取資源時,當資源自第一次獲取那個實際點發生更改后才再次發生數據,否則將使用客戶端緩存的數據。

在一些適當的場合,實現此方法可以更有效的利用網絡資源,減少不必要的數據發送。

2、如果getLastModified方法的返回值是一個正數,那就要分以下兩種情況考慮:

??? (1)如果請求頭沒有包含If-Modified-Since頭字段(應該是第一次訪問資源時候) 或者 其getLastModified返回值比If-Modified-Since頭字段指定時間,則調用doGet返回生成response?和?設置Last-Modified 消息頭

??? (2)如果其getLastModified返回值比If-Modified-Since頭字段指定時間,則返回一個304狀態給客戶端,表示讓客戶端繼續使用以前緩存的頁面

比如說 304 這個場景我在《?JavaEE 要懂的小事:一、圖解Http協議?》文章中提到,第一次訪問 百度 首頁時,有些資源會成功獲取 返回200再次F5,有些資源或直接調用客戶端的緩存數據,則返回304

image1_thumb

三、Servlet線程問題

Servlet容器可以并發路由多個請求到 Servlet 的?service方法。為了處理這些請求,Servlet必須在并發及線程安全問題做好處理。上一篇的《?Servlet必會必知?》提到定義全局變量會造成線程安全問題。在開發Servlet時,考慮線程安全問題提出了一下解決

1、實現?SingleThreadModel?接口

????Servlet2.4 已經提出不提倡使用。實現此接口,Servlet容器為每個新的請求創建一個單獨的Servlet實例。這會有嚴重性能問題

2、同步鎖

??? 使用synchronized關鍵字,雖然可以保證只有一個線程可以訪問被保護區段,已達到保證線程安全。但是系統性能及并發量大大降低。不可取~

3、避免使用實例變量,即Servlet中全局變量。使用局部變量 (推薦)

??? 方法中的局部變量分配在空間,每個線程有私有的棧空間。因此訪問是線程安全的。

我想到了以下一個問題:

既然Sevlet的全局變量是線程不安全的,那SpringMVC?Controller?也一樣。那我們在Controller定義個?XXXService?變量會不會造成線程安全呢?
答:因為這是Spring的一個Service Bean,是線程安全的,所以可以作為單例使用,不會造成線程安全。

四、總結(別忘了點贊哦)

補充文章內容要點:

HttpServlet service 方法詳解

深入理解 代碼 對HTTP狀態碼的運用

Servlet的線程安全問題

歡迎點擊我的博客及GitHub — 博客提供RSS訂閱哦

———-?http://www.bysocket.com/?————-?https://github.com/JeffLi1993?———-

轉載于:https://www.cnblogs.com/Alandre/p/4779897.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375565.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375565.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375565.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

react.js 從零開始(五)React 中事件的用法

事件系統 虛擬事件對象 事件處理器將會傳入虛擬事件對象的實例&#xff0c;一個對瀏覽器本地事件的跨瀏覽器封裝。它有和瀏覽器本地事件相同的屬性和方法&#xff0c;包括 stopPropagation() 和 preventDefault()&#xff0c;但是沒有瀏覽器兼容問題。 如果因為一些因素&#x…

乘積的最大子數組

給你一個整數數組 nums &#xff0c;請你找出數組中乘積最大的連續子數組&#xff08;該子數組中至少包含一個數字&#xff09;&#xff0c;并返回該子數組所對應的乘積。 示例 1: 輸入: [2,3,-2,4] 輸出: 6 解釋: 子數組 [2,3] 有最大乘積 6。示例 2: 輸入: [-2,0,-1] 輸出…

javascript new

1. 僅function可以使用new 2. function使用new時&#xff0c;會拷貝function中this的內容給新對象&#xff0c;并將function的prototype指向新對象&#xff08;如果該function沒有prototype&#xff0c;則指向Object的prototype&#xff09; 注&#xff1a;function本身不是Obj…

!+\v1 用來“判斷瀏覽器類型”還是用來“IE判斷版本”的問題!

這種寫法是利用各瀏覽器對轉義字符"\v"的理解不同來判斷瀏覽器類型。在IE中&#xff0c;"\v"沒有轉義&#xff0c;得到的結果為"v"。而在其他瀏覽器中"\v"表示一個垂直制表符&#xff0c;所以ie解析的"\v1" 為 "v1&quo…

三個數的最大乘積

給定一個整型數組&#xff0c;在數組中找出由三個數組成的最大乘積&#xff0c;并輸出這個乘積。 示例 1: 輸入: [1,2,3] 輸出: 6示例 2: 輸入: [1,2,3,4] 輸出: 24注意: 給定的整型數組長度范圍是[3,104]&#xff0c;數組中所有的元素范圍是[-1000, 1000]。 輸入的數組中任…

VB.NET 數組的定義 動態使用 多維數組

我們都知道在全部程序設計語言中數組都是一個非常重要的概念&#xff0c;數組的作用是同意程序猿用同一個名稱來引用多個變量&#xff0c;因此採用數組索引來區分這些變量。非常多情況下利用數組索引來設置一個循環&#xff0c;這樣就能夠高效地處理復雜的情況&#xff0c;因此…

web.xml 中的listener、 filter、servlet 加載順序

1&#xff1a;首先是context-param節點 2&#xff1a;接著配置和調用listeners 并開始監聽 3&#xff1a;然后配置和調用filters filters開始起作用 4&#xff1a;最后加載和初始化配置在load on startup的servlets轉載于:https://www.cnblogs.com/dwchenxj/p/4787717.html

這么多個月,我頭一次體驗用類的概念來寫驅動

原來感覺一樣是那么爽阿。。。快樂得不得了。。。轉載于:https://www.cnblogs.com/suanguade/p/4038190.html

設置Chrome忽略網站證書錯誤

本人在XP下使用Chrome。總是莫名其妙的提示整數錯誤&#xff0c;一部分https網站無法直接訪問。網上找了下&#xff0c;把解決思路記錄下來。 解決這個問題很簡單,只需要修改你平時用來啟動Chrome的快捷方式就可以忽略掉證書錯誤. 具體的操作方法是這樣的: 找到你的Chrome快捷方…

Android開發之合并文件的幾種方式

以下介紹合并文件的幾種方式&#xff0c;并通過合并amr文件來舉例介紹合并文件的詳細流程。amr格式的文件頭是6字節&#xff0c;所以在進行文件合并的時候要減去除第一個文件以外的其它文件的文件頭。 注意&#xff1a;不同文件的文件頭是不一樣的&#xff0c;所以在合并的時候…

數組中出現次數超過一半的數

數組中有一個數字出現的次數超過數組長度的一半&#xff0c;請找出這個數字。 你可以假設數組是非空的&#xff0c;并且給定的數組總是存在多數元素。 示例 1: 輸入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 輸出: 2限制&#xff1a; 1 < 數組長度 < 50000class Solution { pub…

中國寒龍反網絡病毒聯盟核心小組:官方公告,近期本站將會發布各種編程技術視頻教程,詳情請點擊我們的以下公告!...

大家好&#xff0c;我是中國寒反網絡病毒聯盟官方客服&#xff01; 近期&#xff0c;本站將全面升級&#xff0c;本站發布各種編程視頻教程&#xff0c;包括C,c#以及VB&#xff0c;VB.net&#xff0c;E&#xff0c;等相關編程語言入門視頻教程&#xff0c;每天會定期更新視頻教…

javascript學習-原生javascript的小特效(多個運動效果整理)

以下代碼就不詳細解析了&#xff0c;在我之前的多個運動效果中已經解析好多次了&#xff0c;重復的地方這里就不說明了&#xff0c;有興趣的童鞋可以去看看之前的文章《原生javascript的小特效》 <!DOCTYPE HTML> <html lang"en-US"> <head> <m…

linux在指定目錄多個文件中搜索關鍵字

find 文件目錄 -name *.* -exec grep xxx {} -n\;# -n顯示行號find 文件目錄 -name *.* | xargs grep xxx -ngrep xxx 文件目錄 -Rngrep xxx find 文件目錄 -name *.*

$ npm install opencv ? 你試試?! 在windows環境下,使用node.js調用opencv攻略

博主之前寫過一篇文章《html5與EmguCV前后端實現——人臉識別篇》&#xff0c;敘述的是opencv和C#的故事。最近在公司服務器上更新了一套nodejs環境&#xff0c;早就聽聞npm上有opencv模塊&#xff0c;便欲部署之。然而opencv的部署似乎從來都不會那么順利...... 找模塊上https…

android學習——GestureDetector.OnGestureListener 詳解

Android Touch Screen 與傳統Click Touch Screen不同&#xff0c;會有一些手勢(Gesture)&#xff0c;例如Fling&#xff0c;Scroll等等。這些Gesture會使用戶體驗大大提升。Android中的Gesture識別(detector)是通過GestureDetector.OnGestureListener接口實現的。 首先&#xf…

關于安卓一鍵分享的,急求幫助!

問題描述現在要做一個項目&#xff0c;設置里面點擊一個按鈕就可以分享&#xff0c;有三個分享平臺&#xff0c;新浪微博&#xff0c;微信和微信朋友圈現在的問題是我要在三個平臺分享的內容不同&#xff0c;在新浪微博中分享的是一段文字敘述和一個網頁鏈接&#xff1b;而在微…

和可被 K 整除的子數組

給定一個整數數組 A&#xff0c;返回其中元素之和可被 K 整除的&#xff08;連續、非空&#xff09;子數組的數目。 示例&#xff1a; 輸入&#xff1a;A [4,5,0,-2,-3,1], K 5 輸出&#xff1a;7 解釋&#xff1a; 有 7 個子數組滿足其元素之和可被 K 5 整除&#xff1a;…

前端進階路線圖

CSS不能編程&#xff1f;用Less、Sass、Stylus、甚至直接用 Absurd&#xff0c;框架除了Bootstrap還有很多。JS寫多了很麻煩&#xff1f;jQuery。移動開發&#xff1f;Zepto.js。結構不好&#xff1f;找框架&#xff0c;Backbone.js是MVC&#xff0c;AngularJS和Ember.js是MVVM…

流媒體直播服務LSS

流媒體直播服務LSS posted on 2014-10-22 11:23 實驗室 閱讀(...) 評論(...) 編輯 收藏 轉載于:https://www.cnblogs.com/labs/p/4042641.html