java筆記2-servlet-處理請求與響應

目標

  • 怎么處理請求與響應
    • web容器到底是怎么實現(xiàn)請求與響應的
    • HttpServletRequest處理請求
      • http請求頭信息有哪些
      • get/post獲取參數(shù)
      • get/post編碼
      • 上傳圖片怎么解決笼痹?(http協(xié)議body數(shù)據怎么獲人褡选霹娄?)
      • 容器內部如何共享數(shù)據?
      • 兩個servlet程序之間如何調用?
      • 內部轉發(fā)到底是什么邏輯?
    • HttpServletResponse處理響應
      • http響應頭信息有哪些
      • 輸出內容也是需要編碼的!
      • 二進制響應
      • 重定向
      • 直接輸出錯誤狀態(tài)(404)

1. web容器到底是怎么實現(xiàn)請求與響應的族檬?

Paste_Image.png
  1. web容器接收到HTTP服務器轉發(fā)的請求內容
  2. 初始化HttpServletRequest對象,然后用相關參數(shù)進行賦值
  3. 初始化HttpServletResponse對象
  4. 初始化HttpServlet的實現(xiàn)類化戳,調用它的service函數(shù)单料,并把HttpServletRequest和HttpServletResponse兩個對象傳遞過去
  5. service調用doXXX函數(shù),在該函數(shù)中点楼,使用request的getParamter()函數(shù)獲取參數(shù)
  6. 處理相應的業(yè)務邏輯
  7. 設置response的setContentType輸出文件類型和編碼
  8. 調用HttpServletResponse的getWriter()函數(shù)獲得輸出用的PrintWriter對象扫尖,然后通過函數(shù)println()打印輸出html

需注意的是:

  1. 一次請求和響應是一個生命周期,在該周期呢掠廓,HttpServletRequest和HttpServletResponse由容器負責創(chuàng)建和銷毀换怖,它們不能跨越生命周期
  2. web容器在一個生命周期內處理的流程已經很清晰了,試想蟀瞧,如果沒有web容器沉颂,這些工作都要由程序員每次編碼實現(xiàn)条摸,很復雜!因此容器將系統(tǒng)自身業(yè)務邏輯和軟件需求業(yè)務邏輯進行分離铸屉,開發(fā)人員只需要編寫軟件需求業(yè)務邏輯即可钉蒲!

servlet原來設計是處理各種網絡協(xié)議的,因此提供的請求和響應對象類型是ServletRequest和ServletResponse彻坛,HttpServlet將這兩個對象轉化為HttpServletRequest和HttpServletResponse顷啼,請看具體代碼:

Paste_Image.png

然后在service里面調用實際的doXXX相關函數(shù):

Paste_Image.png

2. HttpServletRequest處理請求

  • http請求頭信息有哪些?

標示字段 含義
Accept 客戶端支持的數(shù)據類型
Accept-Charset 客戶端支持的編碼
Acctpt-Encoding 客戶端支持哪種數(shù)據壓縮格式
Acctpt-Language 客戶端采用的是那種開發(fā)語言
Host 客戶端想訪問的服務器主機
if-Modified-Since 數(shù)據在客戶端緩存的時間
Referer 客戶端從哪個頁面來的
User-Agent 客戶端的操作系統(tǒng)和瀏覽器信息
Cookie cookie數(shù)據
Connection 持否需要持久鏈接
Content_length 表示請求消息正文的長度

這是ljlj的請求頭信息截圖:

Paste_Image.png
  • GET/POST獲取參數(shù)及標頭

取得web應用程序環(huán)境路徑:getContextPath()

獲取參數(shù)

函數(shù) 功能描述
getParameter(參數(shù)名稱) 獲取指定參數(shù)名稱的值
getParameterValues() 同一個請求參數(shù)會有多個值昌屉,返回的是一個數(shù)組钙蒙,返回類型為Enumeration對象
getParameterNames() 返回所有參數(shù)的名稱
getParameterMap 以key/value的方式返回參數(shù)與值

獲取標頭

函數(shù) 功能描述
getHeader(參數(shù)名稱) 獲取指定參數(shù)名稱的標頭
getHeaders() 類似于getParameterValues函數(shù),返回的也是Enumeration對象
getHeaderNames() 返回所有標頭參數(shù)名稱
  • GET/POST編碼

編碼問題主要是針對非ASCII碼字符

-------------------------------post請求-------------------------------

瀏覽器端
Content-Type標頭中會設置字符編碼

Context-Type:text/html;charset=UTF-8

相當于是做了如下操作:

String text = java.net.URLEncoding.encode("林","UTF-8")

容器端
容器端默認的編碼是:ISO-8859-1怠益,所以如果要取得正確的中文字符仪搔,就需要:

req.setCharacterEncoding("UTF-8");
-------------------------------get請求-------------------------------

get請求的瀏覽器端和post一樣,不再贅述蜻牢!

HTTP服務器端
這里為什么和post不一樣,post是容器端偏陪,而這里是HTTP服務器端抢呆?
因為處理URL的是http服務器,而不是web容器笛谦,因此get參數(shù)不能使用HttpServletRequest對象1啊!
get獲取參數(shù)只能是獲得參數(shù)后饥脑,在進行編碼轉換恳邀,它會使用到String對象的getBytes()函數(shù),具體方式如下:

String name = req.getParameter("name");
String name = new String(name.getBytes("ISO-8859-1","UTF-8"));
  • 上傳圖片怎么解決灶轰?(http協(xié)議body數(shù)據怎么獲纫シ小?)

先來確認一下http協(xié)議body數(shù)據是什么笋颤?http協(xié)議一般是由請求行乳附、請求頭部、空行和請求數(shù)據四部分組成的:

Paste_Image.png

GET請求沒有body

GET /hello/index.html HTTP/1.1 
#【↑】request line
#【↓】request headers
Accept: */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
Host: localhost:8000
#發(fā)送完關閉連接 or 等待
Connection: Keep-Alive
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

post請求的表單數(shù)據就是body

#url的部分仍然是urlencoded
POST /hello/checkUser.html?opt=xxx HTTP/1.1
Referer: http://localhost:8000/hello/index.html
Accept: */*
Accept-Language: zh-cn
#純文本的編碼:不編碼
Content-Type: text/plain
Accept-Encoding: gzip, deflate
Host: localhost:8000
Content-Length: 20
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=BBBA54D519F7A320A54211F0107F5EA6

#【↑】/r/n
#【↓】request body
hl=zh-CN&source=hp&q=domety  

搞清楚body的原理后伴澄,把取body數(shù)據分為兩種赋除,一種是簡單的字符串表單,里面的都是文字非凌,另一種就是文件上傳了举农。

---------字符串------------
HttpServletRequest定義了getReader()方法,可以獲得BufferReadere對象敞嗡,通過該對象颁糟,就可以訪問body中的數(shù)據

Paste_Image.png

---------文件(圖片)上傳------------
有兩種方式祭犯,一種是用HttpServletRequest的getInputStream()函數(shù)獲取ServletInputStream對象,是一種串流對象滚停,來處理上傳文件沃粗。另一種就是servlet3.0中使用的Part進行操作。前一種有點落伍键畴,就不贅述了最盅!

使用Part處理上傳圖片,必須加上@WebServlet("/upload.do")

Paste_Image.png
  • 容器內部如何共享數(shù)據起惕?

req.setAttrbute()
req.getAttrbute()
req.getAttrbuteNames()
req.removeAttrbute()

在一個請求的生命周期內涡贱,php共享數(shù)據靠session,java可以設置HttpServletRequest的屬性惹想,來在整個生命周期內问词,不論轉發(fā)了多少個servlet,這些屬性都存在嘀粱。
有些保留的屬性名稱就不要設置了:

Paste_Image.png
  • 兩個servlet程序之間如何調用激挪?

request.getRequestDispatcher("some.do").include(request,response)
request.getRequestDispatcher("some.do?data=xxx").include(request,response)
  • 內部轉發(fā)到底是什么邏輯?

在調用forward函數(shù)前锋叨,當前servlet不能對請求進行響應(例如打印字符串)垄分,如果有響應但未確認(緩沖區(qū)未滿或未調用任何清除方法),則響應設置會被忽略娃磺。如果有效應且已確認薄湿,然后在調用forward()方法,則會拋出IllegalStateException異常

request.getRequestDispatcher("some.do").forward(request.response);

3. HttpServletResponse處理響應

  • http響應頭信息有哪些偷卧?

頭標示 頭標示解釋
Location 表示客戶端應該到哪里去提取文檔
Content-Encoding 文檔的編碼方式
Content-Length 表示內容長度
Content-Type 表示后面的文檔屬于哪種MIME類型
Last-Modified 文檔的最后修改時間
Expires 文檔什么時候過期
Refresh 表示瀏覽器因該在多少時間之后刷新文檔
Server 服務器名字
Set-Cookie 設置和頁面關聯(lián)的cookie
Paste_Image.png

---------------常規(guī)的設置標頭的函數(shù)---------------

  • setHeader() 設置標頭名稱和值
  • addHeader() 給同一標頭名稱上附加值
  • setIntHeader() 如果標頭的值是整數(shù)
  • addIntHeader() 同理
  • setDateHeader() 如果標頭的值是日期時間
  • addDateHeader() 同理

所有的標頭設置必須在響應輸出確認之前豺瘤,如果在之后,所有的設置會被忽略

---------------響應輸出有緩沖區(qū)---------------
只有在緩沖區(qū)滿或者強制刷新緩沖區(qū)的情況下听诸,才會真正的輸出內容到客戶端瀏覽器坐求。

  • getBufferSize()
  • setBufferSize()
  • isCommited() 查看緩沖區(qū)的內容是否已經確認
  • reset()
  • resetBuffer()
  • flushBuffer()

在調用HttpServletResponse的getWrite()或getOutputStream()方法之后調用setBufferSize(),會拋出IllegalStateException蛇更。(也就是在調用輸出函數(shù)之前就得設置好緩沖區(qū))
在響應輸出確認之后瞻赶,調用reset(),resetBuffer()會拋出IllegalStateException異常。(確認的輸出不能隨意重置)

  • 輸出內容也是需要編碼的派任!

HttpServletResponse對象的setCharacterEncoding()和setContextType()都能設置編碼砸逊,建議使用后者,連同文件內容類型一起設置

response.setContextType("text/html","UTF-8")
  • 二進制響應

在大部分情況下掌逛,會從HttpServletResponse取得PrintWriter實例师逸,使用println()對瀏覽器進行字符輸出。但是有時候豆混,需要直接對瀏覽器進行字節(jié)輸出篓像,這時候可以使用HttpServletResponse的getOutputStream()方法取得ServletOutputStream實例动知,他是OutputStream的子類。

區(qū)分字符流輸出和字節(jié)流輸出员辩,前者主要用來處理文字盒粮,包括多國語言的識別。而字節(jié)流主要用來處理文字意外的數(shù)據奠滑,例如二進制文件丹皱,圖片,PDF文件

Paste_Image.png

這段代碼就展示了如果向瀏覽器輸出一個PDF文件宋税,如果瀏覽器有第三方插件可以在線打開這個字節(jié)流pdf文件摊崭,那就直接顯示,否則提示下載杰赛。

  • 重定向

Paste_Image.png
response.sendRedirect("http://xxxxxx.com");

重定向其實也是利用了HTTP狀態(tài)嗎和標頭呢簸,因此重定向前,不能有響應輸出確認乏屯,否則會拋出異常

  • 直接輸出錯誤狀態(tài)(404)

    response.sendError(HttpServletResponse.SC_NOT_FOUND)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末根时,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子瓶珊,更是在濱河造成了極大的恐慌啸箫,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伞芹,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝉娜,警方通過查閱死者的電腦和手機唱较,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來召川,“玉大人南缓,你說我怎么就攤上這事∮牛” “怎么了汉形?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長倍阐。 經常有香客問我概疆,道長,這世上最難降的妖魔是什么峰搪? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任岔冀,我火速辦了婚禮,結果婚禮上概耻,老公的妹妹穿的比我還像新娘使套。我一直安慰自己罐呼,他們只是感情好,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布侦高。 她就那樣靜靜地躺著嫉柴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奉呛。 梳的紋絲不亂的頭發(fā)上计螺,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天叨咖,我揣著相機與錄音分扎,去河邊找鬼竭沫。 笑死栅贴,一個胖子當著我的面吹牛晾咪,可吹牛的內容都是我干的祥楣。 我是一名探鬼主播检访,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼眶拉,長吁一口氣:“原來是場噩夢啊……” “哼罗晕!你這毒婦竟也來了济欢?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤小渊,失蹤者是張志新(化名)和其女友劉穎法褥,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酬屉,經...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡半等,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了呐萨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杀饵。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谬擦,靈堂內的尸體忽然破棺而出切距,到底是詐尸還是另有隱情,我是刑警寧澤惨远,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布谜悟,位于F島的核電站,受9級特大地震影響北秽,放射性物質發(fā)生泄漏葡幸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一羡儿、第九天 我趴在偏房一處隱蔽的房頂上張望礼患。 院中可真熱鬧,春花似錦、人聲如沸缅叠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肤粱。三九已至弹囚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間领曼,已是汗流浹背鸥鹉。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庶骄,地道東北人毁渗。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像单刁,于是被迫代替她去往敵國和親灸异。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理羔飞,服務發(fā)現(xiàn)肺樟,斷路器,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 0 系列目錄# WEB請求處理 WEB請求處理一:瀏覽器請求發(fā)起處理 WEB請求處理二:Nginx請求反向代理 本...
    七寸知架構閱讀 13,921評論 22 190
  • 1. Java基礎部分 基礎部分的順序:基本語法逻淌,類相關的語法么伯,內部類的語法,繼承相關的語法卡儒,異常的語法田柔,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 目標 servlet的生命周期 servletConfig與ServletContext定義,及其二者的區(qū)別 監(jiān)聽...
    arkulo閱讀 949評論 0 5
  • 從三月份找實習到現(xiàn)在骨望,面了一些公司凯楔,掛了不少,但最終還是拿到小米锦募、百度、阿里邻遏、京東糠亩、新浪、CVTE准验、樂視家的研發(fā)崗...
    時芥藍閱讀 42,213評論 11 349