1. 程式人生 > >HttpServletResponse響應頭與HttpServletRequest請求頭及編碼問題

HttpServletResponse響應頭與HttpServletRequest請求頭及編碼問題

 狀態碼:200表示成功、302表示重定向、404表示客戶端錯(訪問的資源不存在)、500表示伺服器端錯
    > sendError(int sc) --> 傳送錯誤狀態碼,例如404、500
    > sendError(int sc, String msg) --> 也是傳送錯誤狀態碼,還可以帶一個錯誤資訊!

    > setStatus(int sc) --> 傳送成功的狀態碼,可以用來發送302

響應頭:Content-Type、Refresh、Location等等
    頭就是一個鍵值對!可能會存在一個頭(一個名稱,一個值),也可能會存在一個頭(一個名稱,多個值!)
    > *****setHeader(String name, String value):適用於單值的響應頭,例如:response.setHeader("aaa", "AAA");
    > addHeader(String name, String value):適用於多值的響應頭
response.addHeader("aaa", "A");
response.addHeader("aaa", "AA");
response.addHeader("aaa", "AAA");
    > setIntHeader(String name, int value):適用於單值的int型別的響應頭
`response.setIntHeader("Content-Length", 888);
    > addIntHeader(String name, int value):適用於多值的int型別的響應頭
    > setDateHeader(String name, long value):適用於單值的毫秒型別的響應頭
response.setDateHeader("expires", 1000 * 60 * 60 * 24);
    > addDateHeader(String name, long value):適用於多值的毫秒型別的響應頭

> <meta>標籤可以代替響應頭:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

* 響應體:通常是html、也可以是圖片!
    > response的兩個流:
      <> ServletOutputStream,用來向客戶端傳送位元組資料。ServletOutputStream out = resopnse.getOutputStream();
      <> PrintWriter,用來向客戶端傳送字元資料!需要設定編碼。PrintWriter writer = response.getWriter();
      <> 兩個流不能同時使用!

* 重定向:設定302,設定Location!其中變化的只有Location,所以java提供了一個快捷方法,完成重定向!
   > sendRedirect(String location)方法

response.setHeader("refresh","3;url='/day06/index.jsp'");設定重新整理

------------------


request --> 封裝了客戶端所有的請求資料!
請求行
請求頭
空行
請求體(GET沒體)


  回憶一下http協議!請求協議中的資料都可以通過request物件來獲取!
  * 獲取常用資訊
    > 獲取客戶端IP,案例:封IP。request.getRemoteAddr()
    > 請求方式,request.getMethod(),可能是POST也可能是GET
  * 獲取HTTP請求頭
    > *****String getHeader(String name),適用於單值頭
    > int getIntHeader(String name),適用於單值int型別的請求頭
    > long getDateHeader(String name),適用於單值毫秒型別的請求頭
    > Enumeration<String> getHeaders(String name),適用於多值請求頭


   案例:
    > 通過User-Agent識別使用者瀏覽器型別
    > 防盜鏈:如果請求不是通過本站的超連結發出的,傳送錯誤狀態碼404。Referer這個請求頭,表示請求的來源!
  * 獲取請求URL
http://localhost:8080/day10_2/AServlet?username=xxx&password=yyy
    > String getScheme():獲取協議,http
    > String getServerName():獲取伺服器名,localhost
    > String getServerPort():獲取伺服器埠,8080
    > *****String getContextPath():獲取專案名,/day10_2
    > String getServletPath():獲取Servlet路徑,/AServlet
    > String getQueryString():獲取引數部分,即問號後面的部分。username=xxx&password=yyy
    > String getRequestURI():獲取請求URI,等於專案名+Servlet路徑。/day10_2/AServlet
    > String getRequestURL():獲取請求URL,等於不包含引數的整個請求路徑。http://localhost:8080/day10_2/AServlet


  * 獲取請求引數:請求引數是由客戶端傳送給伺服器的!有可能是在請求體中(POST),也可能是在URL之後(GET)
    請求引數:有一個引數一個值的,還有一個引數多個值!
    > *****String getParameter(String name):獲取指定名稱的請求引數值,適用於單值請求引數
    > String[] getParameterValues(String name):獲取指定名稱的請求引數值,適用於多值請求引數
    > Enumeration<String> getParameterNames():獲取所有請求引數名稱
    > *****Map<String,String[]> getParameterMap():獲取所有請求引數,

* 請求轉發和請求包含
    RequestDispatcher rd = request.getRequestDispatcher("/MyServlet");  使用request獲取RequestDispatcher物件,方法的引數是被轉發或包含的Servlet的Servlet路徑
    請求轉發:*****rd.forward(request,response);
    請求包含:rd.include(request,response);


    有時一個請求需要多個Servlet協作才能完成,所以需要在一個Servlet跳到另一個Servlet!
    > 一個請求跨多個Servlet,需要使用轉發和包含。
    > 請求轉發:由下一個Servlet完成響應體!當前Servlet可以設定響應頭!(留頭不留體)
    > 請求包含:由兩個Servlet共同未完成響應體!(都留)
    > 無論是請求轉發還是請求包含,都在一個請求範圍內!使用同一個request和response!
  * request域
    Servlet中三大域物件:request、session、application,都有如下三個方法:
    > void setAttribute(String name, Object value)
    > Object getAttribute(String name)
> void removeAttribute(String name);
    > 同一請求範圍內使用request.setAttribute()、request.getAttribute()來傳值!前一個Servlet呼叫setAttribute()儲存值,後一個Servlet呼叫getAttribute()獲取值。


  * 請求轉發和重定向的區別
    > 請求轉發是一個請求一次響應,而重定向是兩次請求兩次響應
    > 請求轉發位址列不變化,而重定向會顯示後一個請求的地址
    > 請求轉發只能轉發到本專案其他Servlet,而重定向不只能重定向到本專案的其他Servlet,還能定向到其他專案
    > 請求轉發是伺服器端行為,只需給出轉發的Servlet路徑,而重定向需要給出requestURI,即包含專案名!
    > 請求轉發和重定向效率是轉發高!因為是一個請求!
      <> 需要位址列發生變化,那麼必須使用重定向!
      <> 需要在下一個Servlet中獲取request域中的資料,必須要使用轉發!

------------------


編碼
  常見字元編碼:iso-8859-1(不支援中文)、gb2312、gbk、gb18030(系統預設編碼,中國的國標碼)、utf-8(萬國碼,支援全世界的編碼,所以我們使用這個)


1. 響應編碼
  * 當使用response.getWriter()來向客戶端傳送字元資料時,如果在之前沒有設定編碼,那麼預設使用iso,因為iso不支援中文,一定亂碼
  * 在使用response.getWriter()之前可以使用response.setCharaceterEncoding()來設定字元流的編碼為gbk或utf-8,當然我們通常會選擇utf-8。這樣使用response.getWriter()傳送的字元就是使用utf-8編碼的。但還是會出現亂碼!因為瀏覽器並不知道伺服器傳送過來的是什麼編碼的資料!這時瀏覽器會使用gbk來解碼,所以亂碼!
  * 在使用response.getWriter()之前可以使用response.setHeader("Content-type","text/html;charset=utf-8")來設定響應頭,通知瀏覽器伺服器這邊使用的是utf-8編碼,而且在呼叫setHeader()後,還會自動執行setCharacterEncding()方法。這樣瀏覽器會使用utf-8解碼,所以就不會亂碼了!
  * setHeader("Content-Type", "text/html;charset=utf-8")的快捷方法是:setContentType("text/html;charset=utf-8)。


**********所以說:想要不亂碼就寫這麼一句:setContentType("text/html;charset=utf-8)。
2. 請求編碼
  * 客戶端傳送給伺服器的請求引數是什麼編碼:
    客戶端首先要開啟一個頁面,然後在頁面中提交表單或點選超連結!在請求這個頁面時,伺服器響應的編碼是什麼,那麼客戶端傳送請求時的編碼就是什麼。
  * 伺服器端預設使用什麼編碼來解碼引數:
    伺服器端預設使用ISO-8859-1來解碼!所以這一定會出現亂碼的!因為iso不支援中文!
  * 請求編碼處理分為兩種:GET和POST:GET請求引數不在請求體中,而POST請求引數在請求體中,所以它們的處理方式是不同的!
  * GET請求編碼處理:

***************獲取亂碼的字串,反編回來,String name =request.getParameter(“name”);name = newString(name.getBytes(“iso-8859-1”), “utf-8”);


  * POST請求編碼處理:
    >request.setCharacterEncoding(“utf-8”);

>String name =request.getParameter(“name”);

3. URL編碼
  表單的型別:Content-Type: application/x-www-form-urlencoded,就是把中文轉換成%後面跟隨兩位的16進位制。
  為什麼要用它:在客戶端和伺服器之間傳遞中文時需要把它轉換成網路適合的方式。


  * 它不是字元編碼!
  * 它是用來在客戶端與伺服器之間傳遞引數用的一種方式!
  * URL編碼需要先指定一種字元編碼,把字串解碼後,得到byte[],然後把小於0的位元組+256,再轉換成16進位制。前面再新增一個%。
  * POST請求預設就使用URL編碼!tomcat會自動使用URL解碼!
  * URL編碼:String username = URLEncoder.encode(username, "utf-8");
  * URL解碼:String username = URLDecoder.decode(username, "utf-8");


  最後我們需要把連結中的中文引數,使用url來編碼!