1. 程式人生 > >JavaWeb學習篇之----容器Response詳解(有關response setCharacterEncoding和setContentType)詳細對比說明

JavaWeb學習篇之----容器Response詳解(有關response setCharacterEncoding和setContentType)詳細對比說明

今天在來看一下Response容器的相關知識,其實這篇blog早就應該編寫了,只是最近有點忙,所以被中斷了。下面我們就來看一下Response容器的相關知識吧。Response和我們即將在後面說到的Request容器是一一對應的,他是web容器在使用者每次請求服務端的時候,建立的一對容器物件,Response容器是服務端返還給客戶機的一個響應內容物件容器,比如說:響應頭,響應行,實體資料等資訊,而Request容器物件是,代表使用者請求服務端的的一個容器物件,比如客戶機的請求頭,請求行,以及攜帶的引數資訊等。所以說Request容器物件和Response容器物件是一一對應的,他們兩的生命週期也是一樣的,就是在一次使用者請求中。下面就來詳細說一下Response容器物件的相關知識吧!

下面先來看一下Response物件的相關方法吧:

addCookie(Cookie cookie):這個方法是向Response容器中新增一個Cookie,然後伺服器容器會自動的將這個Cookie回寫給客戶機的,至於Cookie的相關知識我們會在後面的文章中進行詳解,這篇文章中這個方法暫時用不到。

addDateHeader(String name ,long date):這個是向客戶機新增一個時間值屬性的響應頭資訊,比如那個快取的響應頭expires

addHeader(String name,String value):這個是向客戶機新增一個字串值屬性的響應頭資訊,比如重定向的響應頭location

addIntHeader(String name ,int value):這個是向客戶機新增一個字串屬性的響應頭資訊

containsHeader(String name):這個方法是判斷是否含有這個響應頭資訊欄位

encodeURL(String name):這個方法是用於url改寫的功能的,這個和session有關,等到說session那篇文章的時候在詳細說明

sendRedirect(String name):這個方法是用於請求重定向的,和響應頭中的location欄位的作用相同

setHeader(String name,String value)/setIntHeader(String name,int value)/setDateHeader(String name,long date)

:這些方法和addHeader方法是相對應的,唯一和addHeader不同的是,addHeader是向Response中新增一個響應頭資訊,而setHeader是修改一個響應頭資訊的。

setStatus(int value):通過這個方法是設定響應碼的,比如:200,304,404等。

getOutputStream():通過這個方法可以拿到一個位元組流,然後可以向Response容器中寫入位元組資料,最後客戶機向Response容器中拿去資料進行顯示

getWriter():通過這個方法可以拿到一個字元流(PrintWriter),然後可以向Response容器中寫入字元資料,最後客戶機向Response容器中拿去資料進行顯示

setContentLength():通過這個方法設定伺服器向用戶返回的資料長度,我們在HTTP協議詳解這篇blog中的那個壓縮資料的返回的例子中有說到

setContentType():方法可以直接設定響應頭content-type的內容

下面我們就來詳細介紹一下這些方法的使用吧:

第一個例子:通過Response進行資料的輸出,下面是一個測試的方法,這個方法只要在service方法中呼叫即可,傳遞一個HttpServletResponse物件,就可以進行輸出的

  1. publicvoid test(HttpServletResponse response) throws Exception{  
  2.     // 使用OutputStream位元組流進行資料的輸出
  3.     response.getOutputStream().write("Hello World".getBytes());  
  4. }  

這個例子很簡單就是將字串寫到response容器中,然後客戶機從容器中拿取資料進行顯示即可,但是這裡我們需要注意的,當我們在使用response.getOutputStream()這樣獲取一個OutputStream流的時候,我們在使用完之後,並不需要手動的去關閉,系統會自動關閉它,如果我們手動去關閉這個流的話,還會引發一些問題。

這裡我們輸出的是"Hello World"英文,使用瀏覽器去訪問的時候是沒有亂碼問題,下面我們在將程式碼改寫一下,

  1. response.getOutputStream.write("中國".getBytes("utf-8"));  
這時候我們使用瀏覽器去訪問資料的時候,當然我們可能會看到"中國",也有可能看到的是亂碼,原因很簡單,如果瀏覽器使用的是gb2312碼錶開啟的話,就是亂碼,如果是使用utf-8碼錶開啟的話,就是正常的資料。當然我們可以手動的去設定瀏覽器的開啟碼錶,預設的是gb2312(系統預設碼錶),那麼如果我們使用utf-8將資料寫入到Response中,然後瀏覽器使用的是預設的碼錶去拿取資料進行顯示,那肯定是亂碼了,那麼我們該怎麼辦呢?,讓使用者手動的去修改瀏覽器的開啟碼錶,那貌似太噁心了,所以這裡我們就要介紹一個響應頭欄位的作用了,Content-type:這個頭就是告訴瀏覽器以什麼方式開啟資料,並且指定相應的碼錶,具體程式碼如下:
  1. response.setHeader("Content-type""text/html;charset=utf-8");  
這樣,我們就可以告訴瀏覽器以utf-8碼錶去顯示資料,這樣也就不會再有亂碼的問題了。

這裡我們在擴充套件一下就是還有一種方式控制瀏覽器的開啟碼錶,那就是使用<meta>標籤來實現:

  1. response.getOutputStream().write("<meta http-equiv='content-type' content='text/html;charset=utf-8'>".getBytes());  
這裡我們組建了一個<meta>標籤,並將這個標籤寫入到Response容器中,當客戶機使用去拿取這段資料的時候,發現有html中的標籤<meta>所以會通過一些處理會把上面的字串當做是是html程式碼來顯示。這裡使用了<meat>標籤來解決亂碼問題的。

上面使用的是位元組流的方式來給客戶機發送資料的,有時候我們可能會使用字元流來顯示資料,因為字元流在特定場合下回比位元組流更方便的輸出,其實這裡使用response.getWriter()來獲取一個PrintWriter字元流物件,然後我們可以使用PrintWriter物件的write方法直接寫字串資料,但是這裡也是需要來解決亂碼的問題,而且這裡的需要解決的問題比上面的位元組流更麻煩。下面來看一下吧:

  1. response.getWriter.write("中國");  
通過上面的方法進行輸出,顯示的是亂碼,首先servlet將"中國"字串寫入到Response容器中,但是這裡需要注意的一個問題就是,將"中國"寫入到Response中,那麼Response容器中是怎麼儲存"中國"字串的,因為Response這些技術都是老外發明的,所以他們肯定是使用iso8859-1編碼來進行儲存位元組資料的,所以這裡就會有一個大問題,因為我們知道iso8859-1使用的是單個位元組表示一個字元的,而gb2312使用的是兩個位元組,utf-8使用的是三個位元組,所以Response將使用iso8859-1碼錶進行編碼,那麼儲存的是兩個亂碼位元組,所以,當客戶機從Response容器中去拿取資料的時候顯示的肯定是亂碼,那麼當我們使用
  1. response.setHeader("Content-type","text/html;charset=utf-8")  
來設定瀏覽器的開啟資料的碼錶,但是我們會發現還是顯示兩個??,這個也是很簡單的,因為我們在編寫JavaSE中,也會知道這個問題就是將utf-8這種多位元組的碼錶轉到低位元組碼錶iso8859-1,當我這時候在將結果轉成utf-8的資料,這時候是不可能在轉回原始資料的。所以說我們應該去修改Response容器的碼錶,將其碼錶改成utf-8,這時候就可以"中國"寫入到Response容器中,而且會以utf-8的碼錶進行儲存的,當客戶機在用utf-8碼錶開啟的時候就不會有問題了,

上面我們使用位元組流來進行書寫資料的時候,是沒有問題的,因為是將"中國"的位元組資料直接寫到Response容器中的,所以不會涉及到Response容器編碼的問題。

所以說當我們在使用字元流寫入資料的時候,我們一定要記得修改Response容器的編碼,不然會出現亂碼的

  1. response.setCharacterEncoding("utf-8");  
  2. response.setHeader("content-type""text/html;charset=utf-8");  
所以要用這兩行程式碼的,同時response物件中還有一個方法:setContentType,這個方法可以直接設定Content-type欄位的值
  1. response.setContentType("text/html;charset=utf-8");  
其實這一行程式碼就相當於上面的兩行程式碼的效果,因為在setContentType方法中已經呼叫了setCharacterEncoding方法設定了Response容器的編碼了。

下面我們在來看一下怎麼通過響應頭實現下載的,這裡我們只是來解決一下下載的檔名是中文的情況:

下面圖片就是我們沒有去解決檔名是中文的問題。瀏覽器會過濾中文,並且瀏覽器會認為其是html型別的資料


下面我們使用URLEncoder.encode(filename,"utf-8");來將中文名進行編碼

  1. //實現下載
  2. publicvoid test3(HttpServletResponse response) throws Exception{  
  3.     /** 
  4.     * 這時候就需要通過url進行編碼 
  5.     */
  6.     ServletContext context = this.getServletContext();  
  7.     //通過context方式直接獲取檔案的路徑
  8.     String path = context.getRealPath("/download/美女.jpeg");  
  9.     //獲取檔名
  10.     String filename = path.substring(path.lastIndexOf("\\")+1);  
  11.     //將檔名進行URL編碼
  12.     filename = URLEncoder.encode(filename,"utf-8");  
  13.     //告訴瀏覽器用下載的方式開啟圖片
  14.     response.setHeader("content-disposition""attachment;filename="+filename);  
  15.     //將圖片使用位元組流的形式寫給客戶機
  16.     InputStream is = this.getServletContext().getResourceAsStream("/download/美女.jpeg");  
  17.     OutputStream out = response.getOutputStream();  
  18.     byte[] buffer = newbyte[1024];  
  19.     int len = 0;  
  20.     while((len=is.read(buffer))!=-1){  
  21.         out.write(buffer, 0, len);  
  22.     }  
  23. }  
處理之後的效果:


這次就可以正常顯示檔名了,而且型別也是jpeg的型別

下面在來看一個例子,就是使用response.getOutputStream流做一個驗證碼圖片的實現案例:

原理:首先我們使用BufferedImage物件獲取一個特定高和寬的快取圖片,然後我們將對這個圖片物件進行一些修飾加工

setBorder()來設定圖片的邊框

setBackground來設定圖片的背景顏色

drawRandomLine來設定隨機線條

drawRandomNumber來設定隨機數字

然後通過響應頭Content-type告訴瀏覽器以圖片的方式開啟資料

最後在使用ImageIO物件的write方法將圖片寫入到response.getOutputStream流中

程式碼如下:

  1. <span style="white-space:pre">  </span>//實現隨機圖片的產生
  2.     publicvoid test4(HttpServletResponse response) throws Exception{  
  3.         finalint width = 120;//寬
  4.         finalint height = 35;//高
  5.         BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);  
  6.         Graphics g = image.getGraphics();  
  7.         //設定背景色
  8.         setBackground(g,width,height);  
  9.         //設定邊框
  10.         setBorder(g,width,height);  
  11.         //設定隨機線條
  12.         drawRandomLine(g,width,height);  
  13.         //設定隨機數
  14.         drawRandomNumber((Graphics2D)g,width,height);  
  15.         //不要快取
  16.         /*response.setDateHeader("expires", -1); 
  17.         //告訴所有瀏覽器不要快取 
  18.         response.setHeader("Cache-control", "no-cache"); 
  19.         response.setHeader("Pragma", "no-cache");*/
  20.         response.setHeader("content-type""image/jpeg");  
  21.         ImageIO.write(image,"jpg",response.getOutputStream());  
  22.     }  
  1. <span style="white-space:pre">  </span>/** 
  2.      * 設定背景色 
  3.      * @param g 
  4.      * @param width 
  5.      * @param height 
  6. 相關推薦

    JavaWeb學習----容器Request

    前篇說到了Response容器物件,這篇我們就來看一下Request容器物件,之前也說過了,這個兩個容器物件是相對應的,每次使用者請求伺服器的時候web容器就會給建立這對容器物件,他們是共存亡的,當然Request除了有一個容器物件的角色,他還有一個角色就是Request域

    JavaWeb學習----容器Response有關response setCharacterEncodingsetContentType詳細對比說明

    今天在來看一下Response容器的相關知識,其實這篇blog早就應該編寫了,只是最近有點忙,所以被中斷了。下面我們就來看一下Response容器的相關知識吧。Response和我們即將在後面說到的Request容器是一一對應的,他是web容器在使用者每次請求服務端的

    JavaWeb學習----HTTP協議

    package com.http.demo; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import j

    JavaWeb學習----容器Response

    今天在來看一下Response容器的相關知識,其實這篇blog早就應該編寫了,只是最近有點忙,所以被中斷了。下面我們就來看一下Response容器的相關知識吧。Response和我們即將在後面說到的Request容器是一一對應的,他是web容器在使用者每次請求服務端的時候,

    機器學習中L1L2規則化先驗及稀疏性解釋

    (作者:陳玓玏) 1、 為什麼要正則化? 知乎上有個兄弟說得對(https://www.zhihu.com/question/20924039 這個問題下Stark Einstein的回答),不應該說是正則化,應該說是規則化,也就是說,我們原來是在完全沒有任何先

    javaScript -- touch事件touchstart、touchmovetouchend

    HTML5中新添加了很多事件,但是由於他們的相容問題不是很理想,應用實戰性不是太強,所以在這裡基本省略,咱們只分享應用廣泛相容不錯的事件,日後隨著相容情況提升以後再陸續新增分享。今天為大家介紹的事件主要是觸控事件:touchstart、touchmove和tou

    UNIX檔案許可權尤其是SUIDSGID

    SUID - UNIX下關於檔案許可權的表示方法和解析 SUID UNIX下可以用ls -l 命令來看到檔案許可權。用ls命令所得到的表示法的格式是類似這樣的:-rwxr-xr-x 。 下面解析一下格式所表示的意思,這種表示方法一共有十位:  9 8 7 6 5 4 3 2 1 0  - r w x

    java正則表示式匹配、切割替換

    正則表示式:符合一定規則的表示式。作用:用於專門操作字串。特點:用於一些特定的符號來表示一些程式碼操作,這樣就簡化書寫。所以學習正則表示式,就是在學習一些特殊符號的使用。好處:可以簡化對字串的複雜操作。弊端:符號定義越多,正則越長,閱讀性越差。 具體操作功能: 1,匹配:

    JavaWeb學習----自定義標籤 JSTL標籤庫

                    今天來看一下自定義標籤的內容,自定義標籤是JavaWeb的一部分非常重要的核心功能,我們之前就說過,JSP規範說的很清楚,就是Jsp頁面中禁止編寫一行Java程式碼,就是最好不要有Java指令碼片段,下面就來看一下自定義標籤的簡介:自定義標籤主要用於移除Jsp頁面中的java程

    JavaWeb學習----Jsp

    今天我們來看一下Jsp的相關知識,首先來看看一下Jsp的相關定義: 簡介: JSP全稱是JavaServer Pages,它和servle技術一樣,都是SUN公司定義的一種用於開發動態web資源的技術。 JSP這門技術的最大的特點在於,寫jsp就像在寫html,但: 它相

    JavaWeb學習----自定義標籤&&JSTL標籤庫

    今天來看一下自定義標籤的內容,自定義標籤是JavaWeb的一部分非常重要的核心功能,我們之前就說過,JSP規範說的很清楚,就是Jsp頁面中禁止編寫一行Java程式碼,就是最好不要有Java指令碼片段,下面就來看一下自定義標籤的簡介: 自定義標籤主要用於移除Jsp頁面中的ja

    jvm學習筆記對象

    時間 分代 創建 com 詳解 要求 技術 wid src 一、對象的組成            對象頭(Header):           運行時數據:存儲對象運行時的數據,如哈希碼、GC分代年齡、鎖狀態標誌、線程持有的鎖、偏向線程ID、偏向時間戳等,這部分數據官方成為

    Memcached學習筆記三:MemCached原理

    memcached是一個高效能的分散式記憶體快取伺服器,memcached在Linux上可以通過yum命令安裝,這樣方便很多,在生產環境下建議用Linux系統,memcached使用libevent這個庫在Linux系統上才能發揮它的高效能。它的分散式其實在服務端是不具有分散式的特徵的,是依靠客戶端

    JavaWeb學習----JSP內建物件---九大內建物件沒cook JavaWeb學習----JSP內建物件

    JavaWeb學習----JSP內建物件詳解 JSP共有以下9大內建物件: out request response session pageContext application config page exception 文章連結 -

    高併發併發容器從入門到超神

    一、ConcurrentHashMap 在上面已經提到過ConcurrentHashMap,ConcurrentHashMap相比Hashtable能夠進一步提高併發性,其原理圖如下: HashMap,Hashtable與ConcurrentHashMap都是

    【Java入門提高】Day34 Java容器十五WeakHashMap

    public class WeakHashMapTest { public static void main(String[] args){ testWeakHashMap(); } private static void testWeakHashMap

    三維深度學習pointnet系列

    三維深度學習之pointnet系列詳解(一) 置頂 2018年05月09日 23:25:06 痛並快樂著呦西 閱讀數:4429 標籤: pointnet 三維深度學習 更多 個人分類: 3D Deep Learning

    hadoop家族學習路線圖hadoop產品

    大資料這個詞也許幾年前你聽著還會覺得陌生,但我相信你現在聽到hadoop這個詞的時候你應該都會覺得“熟悉”!越來越發現身邊從事hadoop開發或者是正在學習hadoop的人變多了。作為一個hadoop入門級的新手,你會覺得哪些地方很難呢?執行環境的搭建恐怕就已經足夠讓新手頭疼

    【系統學習SpringBoot】再遇Spring Data JPAJPA應用自定義查詢及複雜查詢

    在此,對Spring Data Jpa做詳細的筆記(使用層面的,原理層日後再說哈哈。) 一、Spring Data JPA設定建立方式: 建立方式一共分為四種: #配置資料庫,使用SpringJPA spring: datasource:

    cocos2d-x box2d物理引擎深入研究 第一旋轉關節(b2RevoluteJoint)

    對於旋轉關節場常見的包括如下: 滾輪或滾筒鏈條或懸橋(使用多個旋轉聯結器)破布娃娃的關節轉門,彈射器,槓桿建立旋轉關節 建立旋轉關節首先設定b2RevoluteJointDef屬性,然後用世界物件建立之. 然後我們看一堆關於旋轉關節的屬性。 localAnchorA - 基