日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Servlet基础之HttpServletResponse详解

發(fā)布時間:2024/9/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Servlet基础之HttpServletResponse详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在上一文中,我們詳細(xì)的介紹了HttpServletRequest對象,并且重點的介紹一個Http請求中包含請求行、請求頭、請求體三部分,并且講解了如何通過HttpServletRequest中封裝的方法來方便的獲取對應(yīng)的頭信息及用戶的請求參數(shù)。


? 在上文中我們也講到了Servlet的功能和重要性,其在MVC架構(gòu)中充當(dāng)Controller的角色,因此其不僅要獲取客戶端的數(shù)據(jù)(用戶輸入的表單數(shù)據(jù)、查詢參數(shù)等),并在處理結(jié)束后,給客戶端一個響應(yīng),也正如我們上圖中所示,Servlet需要對客戶端的HTTP請求進(jìn)行一個HTTP響應(yīng)。而Http的響應(yīng)正是由本文中的主角HttpServletResponse來完成的,下面就讓我們一起學(xué)習(xí)如何對一個Http請求作出正確(適當(dāng)?shù)?#xff0c;處理成功或失敗、無權(quán)限、參數(shù)錯誤等)的響應(yīng)。其局部(省去了Servlet容器)的執(zhí)行過程如下圖所示:


1.設(shè)置響應(yīng)的狀態(tài)碼
? 這里我們通過一個截圖來看下什么是響應(yīng)的狀態(tài)碼,滴、滴、滴(😅,用圖就用全套,此部分圖片來自上篇文章),下圖最大的紅框中的綠色小燈泡旁的200字樣,就是我們這里說的狀態(tài)碼了,綠燈表示其為響應(yīng)成功。


? 有些同學(xué)可能會比較疑惑了,我在開發(fā)的過程中并沒有設(shè)置response的狀態(tài)碼為200呀,怎么這里的200是哪來的?這里需要給大家說一下了,在我們程序正常執(zhí)行(完整的處理了Http請求,沒發(fā)生bug)的時候,Web服務(wù)器會默認(rèn)產(chǎn)生一個狀態(tài)碼為200。還有,在我們url路徑輸錯的時返回的404錯誤,調(diào)用servelt發(fā)生異常直接拋出返回的500錯誤等,都是web服務(wù)器幫我們默認(rèn)產(chǎn)生的。

?
? 在開發(fā)的過程中,500錯誤是我們遇到最多的錯誤了,如空指針異常、sql異常、狀態(tài)異常等導(dǎo)致的請求中斷,對于這些異常,如果直接將報錯信息暴露給用戶,那么我們的系統(tǒng)的體驗就會非常的差。為了增加系統(tǒng)的用戶友好程序,我們必須對異常進(jìn)行處理,但是也需要將錯誤信息正確的提示給用戶,讓其可以有下一步處理或者聯(lián)系客服。

? 這樣我們就需要來設(shè)置狀態(tài)碼,讓前端可以根據(jù)狀態(tài)碼及其他返回信息進(jìn)行相應(yīng)的頁面處理了。那么問題來了,我們?nèi)绾问謩拥脑O(shè)置狀態(tài)碼呢?HttpServletResponse中為我們提供了一下幾個方法:


? 其中比較重要的方法為setStatus(int sc),我們可以通過其方便的設(shè)置給客戶端響應(yīng)的狀態(tài)碼;對于sendError()的兩個方法,會將Servlet之前寫入緩沖區(qū)的數(shù)據(jù)全部清除,但是其也有較好的使用場景,就是對同一種異常設(shè)置專門的錯誤提示頁面,比如用戶未登錄,可以在過濾器(Filter)中判斷出此種情況,并直接調(diào)用sendError跳轉(zhuǎn)至相應(yīng)的頁面,在此頁面上友好的向用戶提示錯誤信息,but此功能完全可以使用重定向來完成,且重定向可以獲取更多的請求和響應(yīng)信息,因此算是一個比較雞肋的功能吧。

? 我們簡單的對setStatus、sendError進(jìn)行測試,這里我們新建個Servelt,命名為ResponseTestServlet,其doGet代碼如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ? ? ? ? ? ??? ??? ??? ??? ?ServletException, IOException {
? //設(shè)置返回客戶端的contentType
? response.setContentType("text/html;charset=utf-8");
? //設(shè)置狀態(tài)碼
? response.setStatus(500);
? //response.sendError(500);
? //獲取輸出流
? PrintWriter out = response.getWriter();
? out.println("雖然我的狀態(tài)為500,但是信息正常輸出了");
}
1
2
3
4
5
6
7
8
9
10
? 我們直接在瀏覽器中調(diào)用ResponseTestServlet,其運行結(jié)果如下圖圖左所示:

?
? 當(dāng)我們執(zhí)行response.sendError(500)時,我覺得大家應(yīng)該都已經(jīng)預(yù)料到結(jié)果頁面了,其結(jié)果如上圖圖右所示。那我們應(yīng)該如何設(shè)置錯誤碼對應(yīng)的錯誤頁面呢?這里我們需要在web.xml中增加如下配置,需要注意的是,配置的路徑必須以’/'開頭,即必須是絕對路徑===打包發(fā)布時的路徑(可參考此文):

<error-page>
? <error-code>500</error-code>
? <location>/index.jsp</location>
</error-page>
1
2
3
4
? 在此在瀏覽器上執(zhí)行,其運行結(jié)果如下圖所示(偷個懶,沒有寫錯誤顯示頁面😅):


? 如何根據(jù)錯誤信息,設(shè)置合理的狀態(tài)碼呢?這就需要我們知道每個狀態(tài)碼表示的含義。Http錯誤碼總共分為5類,即1xx、2xx、3xx、4xx、5xx,分別表示通知信息、成功信息、重定向信息、客戶端錯誤、服務(wù)端錯誤,下面列舉一些常見的錯誤碼:

Name?? ?discribtion?? ?釋義
200?? ?SC_OK?? ?此次請求已經(jīng)成功
301?? ?SC_MOVED_PERMANENTLY?? ?請求的網(wǎng)頁已永久移動到新位置
302?? ?SC_MOVED_TEMPORARILY?? ?臨時移動、請求地址不變
401?? ?SC_UNAUTHORIZED?? ?未授權(quán)、用戶需登錄
403?? ?SC_FORBIDDEN?? ?服務(wù)器拒絕了此次請求(權(quán)限問題)
404?? ?SC_NOT_FOUND?? ?服務(wù)器沒找到URI匹配的
405?? ?SC_METHOD_NOT_ALLOWED?? ?調(diào)用的方法不允許使用(get、post不匹配)
500?? ?SC_INTERNAL_SERVER_ERROR?? ?服務(wù)器內(nèi)部發(fā)生異常,請求中斷
502?? ?SC_BAD_GATEWAY?? ?網(wǎng)關(guān)錯誤(如Nginx),無法收到服務(wù)器的響應(yīng)
504?? ?SC_GATEWAY_TIMEOUT?? ?請求超時,在約定時間內(nèi)沒有收到Http響應(yīng)
2.設(shè)置響應(yīng)消息頭
? 在上文中,我們在chrom調(diào)試工具中查看了Http請求的請求頭、請求體,Chrome提供的信息不止于此,我們來看下圖,可以看到,Response的Headers信息。


? 這也說明了,相應(yīng)于Request中的請求頭,Response也有對應(yīng)的響應(yīng)頭,這些響應(yīng)頭主要如下圖所示:


? 當(dāng)然,為了方便的設(shè)置響應(yīng)頭中對應(yīng)的信息,HttpServletResponse也提供了一系列的方法,主要相關(guān)方法如下:


? 需要注意的是,addHeader、addIntHeader、addDateHeader都有一個對應(yīng)的setxxxx方法,兩者的區(qū)別就如同集合和列表,setxxxx方法不允許出現(xiàn)重復(fù)的header,而addxxxx方法可以;setContentType、setCharacterEncoding方法皆是是指返回給客戶端的內(nèi)容的編碼方式的,推薦直接使用setContentType設(shè)置客戶端內(nèi)容的MIME類型及編碼方式,比如setContentType("text/html; charset=UTF-8")等價于setContentType("text/html");setCharacterEncoding("charset=UTF-8")兩條語句同時執(zhí)行。

? 這里,為了演示上面這些方法,我們將ResponseTestServlet中的doGet方法修改如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ? ? ? ? ? ??? ??? ??? ??? ?ServletException, IOException {
? //設(shè)置返回客戶端的contentType
? response.setContentType("text/html;charset=utf-8");
? //設(shè)置狀態(tài)碼
? //response.setStatus(500);
? //response.sendError(500);
? PrintWriter out = response.getWriter();
? //out.println("雖然我的狀態(tài)為500,但是信息正常輸出了");
? //添加類型為String的header
? response.addHeader("Location", "#");
? //添加類型為long的header
? response.addDateHeader("Date", new Date().getTime());
? //創(chuàng)建一個Cookie
? Cookie cookie = new Cookie("name", "李子樹");
? //添加一個cookie
? response.addCookie(cookie);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
? 其執(zhí)行結(jié)果如下圖所示,我們添加的header都能看到:


3.發(fā)送響應(yīng)消息體
? 前面說了這么多,到了這里才是真正的重頭戲!這里才是最直觀的響應(yīng)給客戶看到的內(nèi)容,在早期JSP還沒有誕生的時代,許多動態(tài)頁面是通過在Serlvet中使用HttpServletResponse輸出到頁面上的,就算到現(xiàn)在,教材上仍有這部分的演示代碼。下面,就讓我們一起來看下HttpServletResponse是如何發(fā)送消息體到客戶端的。

? 首先我們來看兩個HttpServletResponse提供的兩個方法:


? 從中我們可以看到,getOutputStream()方法返回ServletOutputStream對象,更適合向客戶端寫入二進(jìn)制數(shù)據(jù),并且Servlet容器不會對這些二進(jìn)制數(shù)據(jù)進(jìn)行編碼,因此我們常用ServletOutputStream來向客戶端發(fā)送如圖片、文件等內(nèi)容;對于getWriter()方法返回的PrintWriter對象,里面封裝了更多的寫入字符文本的函數(shù),并且我們上文提到的setContentType()方法設(shè)置的MIME類型對其輸出內(nèi)容有效,因此也可以很好地解決中文亂碼問題。

? 還有一點需要注意的是,這兩個方法在一個response對象中不可以同時調(diào)用,否則會拋出一個IllegalStateException,也就是非法狀態(tài)異常,因為輸出流只能有一個(如果可以多次獲取的話,客戶端又如何確認(rèn)哪個Http響應(yīng)是最后一個呢)。

? 下面我們對來簡單的介紹下ServletOutputStream對象和PrintWriter對象中的方法,我們首先來看下ServletOutputStream這個對象(抽象類)的概述(Outline),可以看到,其重載了幾乎可以輸出各種數(shù)據(jù)類型的print()、println()方法,但是通過查看源碼可以發(fā)現(xiàn),這些方法都是通過其父類OutputStream(java.io.OutputStream)的write()方法進(jìn)行的消息體的輸出。


? 下面我們來看下PrintWriter對象的概述,其方法較多,我們只截取部分主要方法,如下圖所示,PrintWriter中提供的輸出方法更多,其輸出方法都是通過Writer(java.io.Writer)類中的write()方法來進(jìn)行的消息體的輸出。

?
? 因為PrintWriter的輸出功能在前面已經(jīng)使用N遍了,下面我們主要演示下如何通過ServletOutputStream來輸出內(nèi)容下面我們簡單的通過代碼演示下ServletOutputStream的使用,我們在ResponseTestServlet中的doGet中代碼修改如下(注釋之前的部分):

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ? ? ? ? ? ??? ??? ??? ??? ?ServletException, IOException {
? //設(shè)置返回客戶端的contentType
?? ?response.setContentType("text/html;charset=utf-8");
??
? //...
??
? ServletOutputStream out = response.getOutputStream();
? //通過ServletOutputStream向客戶端輸出值
? out.print("We Are Young Man!");
}
1
2
3
4
5
6
7
8
9
10
? 其執(zhí)行結(jié)果如下圖所示,瀏覽器中輸出了Servlet給的響應(yīng)。


? 這么看,ServletOutputStream和PrintWriter似乎沒什么區(qū)別,ServletOutputStream一樣可以輸出字符串呀,但是,注意了,當(dāng)我們吧輸出內(nèi)容改為中文,代碼修改為out.print("我們不一樣!");,讓我在來看下執(zhí)行結(jié)果:


? 啥情況,居然發(fā)生了錯誤?代碼中不是通過setContentType設(shè)置了編碼格式為UTF-8了么,為什么頁面中會提示不是ISO 8859-1字符?這里我們在回過頭來看一句話,ServletOutputStream輸出二進(jìn)制數(shù)據(jù),并且Servlet容器不會對這些二進(jìn)制數(shù)據(jù)進(jìn)行編碼,這里就是說,你輸入二進(jìn)制流是什么,Servlet容器不會對你的輸出流編碼,因此上面setContentType是無效的。那有為什么會產(chǎn)生異常呢,我們來看下ServletOutputStream中的print(String s)的源碼。(注意,println方法中調(diào)用的print方法)


public void print(String s) throws IOException {
? if (s==null) s="null";
? int len = s.length();
? for (int i = 0; i < len; i++) {
? ? char c = s.charAt (i);

? ? // XXX NOTE: ?This is clearly incorrect for many strings,
? ? // but is the only consistent approach within the current
? ? // servlet framework. ?It must suffice until servlet output
? ? // streams properly encode their output.
? ? //
? ? if ((c & 0xff00) != 0) { ? ? ? ?// high order byte must be zero
? ? ? String errMsg = lStrings.getString("err.not_iso8859_1");
? ? ? Object[] errArgs = new Object[1];
? ? ? errArgs[0] = Character.valueOf(c);
? ? ? errMsg = MessageFormat.format(errMsg, errArgs);
? ? ? throw new CharConversionException(errMsg);
? ? }
? ? write (c);
? }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
? 注意下中間的一段注釋,明確的告知了這個方法對許多字符是不正確的,iso 8859-1編碼方式完全不支持中文,因此這里在轉(zhuǎn)換的過程中會直接的拋出異常,我們在上個運行結(jié)果上看到的報錯信息的根由也是在此。

? 通過源碼我們也可以看到,print并沒有進(jìn)行轉(zhuǎn)碼,只是判斷一個字節(jié)的高地址的一個字節(jié)(8位)是否為0(注:iso 8859-1只使用了一個字節(jié)來進(jìn)行編碼),一次來判斷字符是否是iso 8859-1字符集中的字符。那這樣的話,ServletOutputStream就真的無法輸出中文了么?


? 山重水復(fù)疑無路,柳暗花明又一村。如果Servlet容器不對二進(jìn)制數(shù)據(jù)進(jìn)行任何的處理,那么,我們是不是可以換個思路?直接將String轉(zhuǎn)為指定編碼方式的byte[](字節(jié)數(shù)組),并通過ServletOutputStream中的write(byte b[])方法將字符數(shù)組輸出的到客戶端。對應(yīng)的,我們將上面的代碼修改如下:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ? ? ? ? ? ??? ??? ??? ??? ?ServletException, IOException {
? //設(shè)置返回客戶端的contentType
?? ?response.setContentType("text/html;charset=utf-8");
??
? //...
??
? ServletOutputStream out = response.getOutputStream();
? //通過ServletOutputStream向客戶端輸出值
? //通過getBytes獲取字節(jié)數(shù)組,并指定編碼方式
? out.print("我們不一樣!".getBytes("UTF-8"));
}
1
2
3
4
5
6
7
8
9
10
11
? 其運行結(jié)果也如下所示:


? 我么可以看到,瀏覽器中正常的顯示了中文輸出。但是如果我們的每個含有中文的字符串都需要使用這種方式輸出,那不是態(tài)麻煩了。這也是我們在描述ServletOutputStream是說的,其適合(suitable)輸出二進(jìn)制數(shù)據(jù)。因此在對客戶端的Http請求進(jìn)行響應(yīng)式,我們也要選擇合理的輸出方式。

4.總結(jié)
? 本文主要講解了Servlet如何對Http請求進(jìn)行響應(yīng),Http響應(yīng)對應(yīng)Http請求的三部分內(nèi)容,分別為響應(yīng)行、響應(yīng)頭和消息體,以及對應(yīng)的如何通過HttpServletResponse設(shè)置對應(yīng)的狀態(tài)碼、響應(yīng)頭,并詳細(xì)的解釋了getOutputStream()和getWriter()的區(qū)別及其使用場景。

參考閱讀:Http1.1狀態(tài)碼定義

? 又到了分隔線以下,本文到此就結(jié)束了,本文內(nèi)容全部都是由博主自己進(jìn)行整理并結(jié)合自身的理解進(jìn)行總結(jié),如果有什么錯誤,還請批評指正。

? Java web這一專欄會是一個系列博客,喜歡的話可以持續(xù)關(guān)注,如果本文對你有所幫助,還請還請點贊、評論加關(guān)注。

? 有任何疑問,可以評論區(qū)留言。
————————————————
版權(quán)聲明:本文為CSDN博主「李子樹_」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_34666857/article/details/104838171

總結(jié)

以上是生活随笔為你收集整理的Servlet基础之HttpServletResponse详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久三| 在线免费观看一区二区 | 喷潮在线 | 78m78成人免费网站 | 成熟丰满熟妇高潮xxxxx视频 | 伊人春色网站 | 香蕉视频在线视频 | 日韩精品国产一区 | 精品福利一区二区三区 | 中文字幕无码精品亚洲资源网久久 | 国产欧美一区二区三区在线看蜜臀 | 怡红院精品视频 | 精品久久久久久久久久久 | 五月天激情视频在线观看 | 国产精品一区二区三区四区五区 | 精品久久久久久中文字幕人妻最新 | 性插免费视频 | 男女羞羞在线观看 | 欧美精品一二区 | 韩国日本欧美一区 | av毛片在线免费观看 | 日b视频免费看 | 国产午夜精品理论片在线 | 国产伦精品一区二区三区 | 亚洲www色| 最新中文字幕在线 | 日韩中文字幕有码 | 1000亚洲裸体人体 | 四虎婷婷| 爱爱视频免费看 | av在线黄色 | 久久久999| 欧美精品www | 日韩a在线观看 | 欧美zzz物交| 精品自拍第一页 | 北条麻妃久久精品 | 色资源网站 | 白俄罗斯毛片 | 在线日韩三级 | 在线毛片观看 | 最新国产精品视频 | 天天天天躁天天爱天天碰2018 | 久久久www | 亚洲少妇一区二区三区 | 免费麻豆视频 | 免费簧片在线观看 | 妞妞av | 精品久久国产字幕高潮 | 欧洲亚洲另类 | 777亚洲 | 中文无码精品一区二区三区 | 人人射人人 | 亚洲视屏在线观看 | 欧美色图网址 | 精品久久视频 | 欧美怡红院 | 伊人成人在线 | 伊人精品在线观看 | 国产精品入口麻豆九色 | 免费中文字幕日韩 | √资源天堂中文在线视频 | 日韩中文字幕有码 | 日本黄图 | 国产福利片在线 | 国产黄片一区二区三区 | 日本超碰在线 | 国产又粗又长又黄 | 三度诱惑免费版电影在线观看 | 国产日韩专区 | 国产一级特黄a高潮片 | 久久久久久久久久福利 | 欧美日韩国产高清视频 | 在线 日本 制服 中文 欧美 | 亚洲综合在线五月 | 中文在线8资源库 | 奇米影视999 | 一本久久精品一区二区 | 在线91观看 | 青青草十七色 | 亚洲区一区| 亚洲女同志亚洲女同女播放 | 91中文字幕视频 | 三上悠亚激情av一区二区三区 | 午夜91视频 | 亚洲无色 | 草青青视频 | 日韩手机看片 | 欧美精品系列 | 老妇女玩小男生毛片 | 亚洲国产欧美视频 | 日少妇的逼 | 国产一区二区免费电影 | 免费禁漫天堂a3d | 超碰国产97 | 中文字幕影片免费在线观看 | 午夜一级片 | 欧美日韩www | 亚洲av无码一区二区三区在线 |