05_Response

The Response

響應對象封裝從服務器返回到客戶機的所有信息。在HTTP協(xié)議中赖临,該信息通過HTTP頭或請求的消息體從服務器傳輸?shù)娇蛻魴C胞锰。

1.緩沖

servlet容器被允許,但不是必需的兢榨,以緩沖輸出到客戶端以達到效率目的嗅榕。通常使用緩沖的服務器使其成為默認的,但是允許servlet指定緩沖參數(shù)吵聪。

ServletResponse接口中的以下方法允許servlet訪問和設置緩沖信息:

  • getBufferSize
  • setBufferSize
  • isCommitted
  • reset
  • resetBuffer
  • flushBuffer

這些方法是在ServletResponse接口上提供的凌那,以允許在servlet使用ServletOutputStream或Writer時執(zhí)行緩沖操作。

getBufferSize方法返回正在使用的底層緩沖區(qū)的大小吟逝。如果沒有使用緩沖帽蝶,則該方法必須返回0的int值。

servlet可以通過使用setBufferSize方法請求首選緩沖區(qū)大小块攒。所分配的緩沖區(qū)不需要是servlet所請求的大小励稳,但必須至少與所請求的大小相同。這允許容器重用一組固定大小的緩沖區(qū)囱井,如果合適的話驹尼,可以提供比請求更大的緩沖區(qū)。在使用ServletOutputStream或Writer編寫任何內容之前庞呕,必須調用該方法新翎。如果已經寫入了任何內容或響應對象,則該方法必須拋出IllegalStateException住练。

isCommitted方法返回一個布爾值地啰,指示是否已將任何響應字節(jié)返回給客戶端。flushBuffer方法強制將緩沖區(qū)中的內容寫入客戶機澎羞。

當響應未提交時髓绽,reset方法清除緩沖區(qū)中的數(shù)據(jù)敛苇。在重置調用之前妆绞,servlet所設置的標題、狀態(tài)代碼和調用getWriter或getOutputStream的狀態(tài)也必須被清除枫攀。如果在沒有清除標頭和狀態(tài)代碼的情況下響應沒有提交括饶,則resetBuffer方法將清除緩沖區(qū)中的內容。

如果響應已提交来涨,并調用reset或resetBuffer方法图焰,則必須拋出IllegalStateException。響應及其相關緩沖區(qū)將保持不變蹦掐。

當使用緩沖區(qū)時技羔,容器必須立即將填充緩沖區(qū)的內容刷新到客戶端僵闯。如果這是發(fā)送給客戶機的第一個數(shù)據(jù),則認為響應是提交的藤滥。

2. Headers

Servlet可以使用以下方法設置HTTP響應頭:

  • setHeader
  • addHeader

setHeader方法用一個具有給定名稱和值設置頭鳖粟。前面的header被新的header所代替。如果名稱對于存在了一組header值拙绊,則將這些值清除并替換為新值向图。

addHeader方法為帶有給定名稱的集合添加了一個header值。如果沒有與名稱關聯(lián)的標頭标沪,就會創(chuàng)建一個新集合榄攀。

header可能包含表示int或Date對象的數(shù)據(jù)。HttpServletResponse接口的以下便利方法允許servlet為適當?shù)臄?shù)據(jù)類型設置正確的格式:

  • setIntHeader
  • setDateHeader
  • addIntHeader
  • addDateHeader

要成功地傳輸回客戶端金句,必須在提交響應之前設置headers(而不是trailer)檩赢。在響應提交后設置的頭(非掛載)將被servlet容器忽略。如果在RFC 7230中指定的HTTP trailer將在響應中被發(fā)送违寞,則必須使用HttpServletResponse的setTrailerFields()方法來提供漠畜。此方法必須在已寫入的chunked響應中的最后一個塊之前調用。

Servlet程序員負責確保為Servlet生成的內容在響應對象中適當?shù)卦O置content-type頭坞靶。HTTP 1.1規(guī)范不要求在HTTP響應中設置這個頭憔狞。當Servlet程序員不設置類型時,Servlet容器不能設置默認的內容類型彰阴。

建議容器使用X-Powered-By HTTP頭來發(fā)布其實現(xiàn)信息瘾敢。字段值應該包含一個或多個實現(xiàn)類型,例如“Servlet/4.0”尿这〈氐郑可選地,容器和底層Java平臺的補充信息可以在括號內的實現(xiàn)類型之后添加射众。容器應可配置以抑制此報頭碟摆。

這里是此header的示例:

X-Powered-By: Servlet/4.0
X-Powered-By: Servlet/4.0 JSP/2.3 (GlassFish Server Open Source
Edition 5.0 Java/Oracle Corporation/1.8)

3.HTTP Trailer

HTTP trailer是一種特殊類型的HTTP報頭,它是在響應主體之后出現(xiàn)的叨橱。trailer是在RFC 7230中指定的典蜕。它們在分塊傳輸編碼和其他通信協(xié)議的實現(xiàn)中很有用。Servlet容器為trailer提供支持罗洗。

如果trailer頭已經準備好讀取愉舔,isTrailerFieldsReady()將返回true。然后伙菜,servlet可以通過HttpServletRequest接口的getTrailerFields()方法讀取HTTP請求的預告頭轩缤。

servlet可以通過為HttpServletResponse接口的setTrailerFields方法提供一個供應商來編寫響應。可以通過訪問HttpServletResponse接口的getTrailerFields()方法獲得trailer頭的供應商火的。

關于規(guī)范規(guī)范的這兩種方法壶愤,請參見javadoc。

4.非阻塞IO

非阻塞IO只適用于servlet和過濾器中的異步請求處理(如第2.3.3.3節(jié)中定義的“異步處理”頁2-10)和升級處理(如第2.3.3.5節(jié)中定義的“升級處理”在第2-21頁)馏鹤。否則公你,必須在ServletInputStream.setReadListener或ServletOutputStream.setWriteListener被調用時拋出IllegalStateException。為了支持Web容器中的非阻塞寫入假瞬,除了第3.7節(jié)中所描述的ServletRequest中所做的更改之外陕靠,在第3-28頁上“非阻塞IO”,還進行了以下更改以處理響應相關的類/接口脱茉。

WriteListener提供了以下回調方法剪芥,容器可以適當?shù)卣{用這些方法。

  • WriteListener
    • void onWritePossible()
      當一個WriteListener注冊到ServletOutputStream時琴许,這個方法將在第一次有可能寫入數(shù)據(jù)時被容器調用税肪。僅當在ServletOutputStream上的isReady方法(描述如下)返回值為false之后容器才會調用onWritePossible方法,寫操作才有可能實現(xiàn)榜田。
    • onError(Throwable t)當處理響應發(fā)生錯誤時調用益兄。
  • ServletOutputStream
    • boolean isReady() 如果對ServletOutputStream將成功,則此方法返回true箭券,否則將返回false净捅。如果該方法返回true,則可以在ServletOutputStream上執(zhí)行寫操作辩块。如果沒有進一步的數(shù)據(jù)可以寫入ServletOutputStream蛔六,那么這個方法將返回false,直到底層數(shù)據(jù)被刷新废亭,此時容器將調用WriteListener的onwriteable方法国章。隨后對該方法的調用將返回true。
    • void setWriteListener(WriteListener listener).
      將WriteListener與這個ServletOutputStream關聯(lián)起來豆村。對于容器液兽,當可以寫入數(shù)據(jù)時,調用WriteListener上的回調方法掌动。注冊一個WriteListener將啟動非阻塞IO四啰。在那個時候切換到傳統(tǒng)的阻塞IO是違法的。在此非法切換到傳統(tǒng)的阻塞IO之后坏匪,使用IO相關的方法調用會產生不確定的行為拟逮。

Servlet容器必須以線程安全的方式訪問WriteListener中的方法。

5.便利方法

以下的便利方法存在于HttpServletResponse接口中:

  • sendRedirect
  • sendError

sendRedirect方法將設置適當?shù)念^和內容主體將客戶機重定向到不同的URL适滓。通過相對URL路徑調用此方法是合法的,但是底層容器必須將相對路徑轉換為完全合格的URL恋追,以便將其傳輸回客戶機凭迹。不管出于什么原因,如果部分URL不能轉化為有效的URL,那么這個方法必須拋出IllegalArgumentException罚屋。

sendError方法將為錯誤消息設置適當?shù)念^和內容體,以返回給客戶機嗅绸∑⒚停可以向sendError方法提供一個可選的字符串參數(shù),該方法可用于錯誤的內容體中鱼鸠。

這些方法將具有提交響應的副作用猛拴,如果它還沒有提交,就終止它蚀狰。在調用這些方法之后愉昆,servlet不應該對客戶機進行進一步的輸出。如果在調用這些方法之后麻蹋,將數(shù)據(jù)寫入響應跛溉,則忽略數(shù)據(jù)。

如果將數(shù)據(jù)寫入響應緩沖區(qū)扮授,但不返回給客戶機(即響應未提交)芳室,則必須清除響應緩沖區(qū)中的數(shù)據(jù),并使用這些方法所設置的數(shù)據(jù)替換刹勃。如果響應被提交堪侯,這些方法必須拋出一個IllegalStateException。

6. 國際化

servlet應該設置響應的語言環(huán)境和字符編碼荔仁。區(qū)域設置使用ServletResponse.setLocale方法抖格。該方法可重復調用;但在做出回應后調用是無效的。如果servlet在提交頁面之前沒有設置語言環(huán)境咕晋,則使用容器的默認語言環(huán)境來確定響應的語言環(huán)境雹拄,但是沒有為與客戶機的通信(比如HTTP中的Content-Language頭)進行規(guī)范。

<locale-encoding-mapping-list>
<locale-encoding-mapping>
<locale>ja</locale>
<encoding>Shift_JIS</encoding>
</locale-encoding-mapping>
</locale-encoding-mapping-list

The <response-character-encoding> element can be used to explicitly set the default encoding for all responses in a given web application.

<response-character-encoding>UTF-8</response-character-encoding>

如果兩個元素都不存在或不提供映射掌呜,則setLocale使用一個容器依賴映射滓玖。可以反復調用setCharacterEncoding质蕉、setContentType和setLocale方法來更改字符編碼势篡。在調用servlet響應的getWriter方法后調用,或在響應提交后調用模暗,對字符編碼沒有影響禁悠。只有當給定的內容類型字符串為charset屬性提供值時,對setContentType的調用才會設置字符編碼兑宇。調用setLocale設置了字符編碼僅當setcharacter編碼或setContentType在之前沒有設置字符編碼碍侦。

如果servlet在調用ServletResponse接口的getWriter方法之前沒有指定字符編碼,或者響應已提交,則使用默認的ISO-8859-1瓷产。

如果使用的協(xié)議提供了這樣做的方法站玄,容器必須與客戶端的語言環(huán)境和用于servlet響應的寫入器的字符編碼通信。在HTTP的情況下濒旦,語言環(huán)境通過Content-Language頭進行通信株旷,字符編碼作為文本媒體類型的內容類型頭的一部分。請注意尔邓,如果servlet沒有指定內容類型晾剖,則無法通過HTTP報頭來傳遞字符編碼;然而,它仍然被用來編碼通過servlet響應的writer寫的文本梯嗽。

7.響應對象的關閉

當響應被關閉時齿尽,容器必須立即將響應緩沖區(qū)中的所有剩余內容刷新到客戶端。以下事件表明servlet滿足了請求慷荔,響應對象將被關閉:

  • servlet的service方法的結束雕什。
  • setContentLength中指定數(shù)量的內容或setContentLengthLong方法回應是大于零的且已經被寫入響應。
  • sendError方法被調用显晶。
  • sendRedirect方法被調用贷岸。
  • AsyncContext的complete方法被調用。

8.響應對象的生存期

每個響應對象只在servlet的service方法的范圍內有效磷雇,或者在過濾器的doFilter方法的范圍內有效偿警,除非關聯(lián)的請求對象為組件啟用了異步處理。如果啟動了相關請求的異步處理唯笙,則響應對象在調用AsyncContext的complete方法之前仍然有效螟蒸。容器通常會回收響應對象,以避免響應對象創(chuàng)建的性能開銷崩掘。開發(fā)人員必須意識到七嫌,在上述范圍之外維護對尚未調用相應請求上的startAsync的響應對象的引用可能會導致非確定性行為。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末苞慢,一起剝皮案震驚了整個濱河市诵原,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌挽放,老刑警劉巖绍赛,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辑畦,居然都是意外死亡吗蚌,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門纯出,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚯妇,“玉大人敷燎,你說我怎么就攤上這事∥甏耄” “怎么了懈叹?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵乖杠,是天一觀的道長分扎。 經常有香客問我,道長胧洒,這世上最難降的妖魔是什么畏吓? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮卫漫,結果婚禮上菲饼,老公的妹妹穿的比我還像新娘。我一直安慰自己列赎,他們只是感情好宏悦,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著包吝,像睡著了一般饼煞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诗越,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天砖瞧,我揣著相機與錄音,去河邊找鬼嚷狞。 笑死块促,一個胖子當著我的面吹牛,可吹牛的內容都是我干的床未。 我是一名探鬼主播竭翠,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼薇搁!你這毒婦竟也來了斋扰?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤只酥,失蹤者是張志新(化名)和其女友劉穎褥实,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裂允,經...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡损离,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了绝编。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僻澎。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡貌踏,死狀恐怖,靈堂內的尸體忽然破棺而出窟勃,到底是詐尸還是另有隱情祖乳,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布秉氧,位于F島的核電站眷昆,受9級特大地震影響,放射性物質發(fā)生泄漏汁咏。R本人自食惡果不足惜亚斋,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望攘滩。 院中可真熱鬧帅刊,春花似錦、人聲如沸漂问。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蚤假。三九已至栏饮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間勤哗,已是汗流浹背抡爹。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芒划,地道東北人冬竟。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像民逼,于是被迫代替她去往敵國和親泵殴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理拼苍,服務發(fā)現(xiàn)笑诅,斷路器,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 從三月份找實習到現(xiàn)在疮鲫,面了一些公司吆你,掛了不少,但最終還是拿到小米俊犯、百度妇多、阿里、京東燕侠、新浪者祖、CVTE立莉、樂視家的研發(fā)崗...
    時芥藍閱讀 42,207評論 11 349
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法七问,內部類的語法蜓耻,繼承相關的語法,異常的語法械巡,線程的語...
    子非魚_t_閱讀 31,597評論 18 399
  • 一只螞蟻一覺醒來刹淌,發(fā)現(xiàn)自己正躺在一片雪地里。 “嘩坟比,下雪了啊芦鳍∪峦”螞蟻感嘆著葛账,伸了個懶腰。 “咦皮仁,不對啊籍琳,怎么一點也...
    椬yi閱讀 647評論 0 0
  • 案例一 長1.40m 寬0.72m 高84cm厚度3cm椅背高度62cm 地點:山東大學 感受:適合仰坐 曲線符合...
    RobinSalt閱讀 2,127評論 0 2