JavaWeb筆記十: response 、 request 、編碼 、 路徑

服務器處理請求的流程:
服務器每次收到請求時,都會爲這個請求開闢一個新的線程。
服務器會把客戶端的請求數據封裝到request對象中,request就是請求數據的載體!(袋子)
服務器還會創建response對象,這個對象與客戶端連接在一起,它可以用來向客戶端發送響應。(手機)


response:

其類型爲HttpServletResponse
  ServletResponse-->與協議無關的類型
  HttpServletResponse-->與http協議相關的類型

  回憶一下http協議!http協議中響應的內容包含哪些東西呢?
  * 狀態碼:200表示成功、302表示重定向、404表示客戶端錯(訪問的資源不存在)、500表示服務器端錯
    > sendError(int sc) --> 發送錯誤狀態碼,例如404、500
    > sendError(int sc, String msg) --> 也是發送錯誤狀態碼,還可以帶一個錯誤信息!
    > setStatus(int sc) --> 發送成功的狀態碼,可以用來發送302
    案例:
    > 發送404
  * 響應頭: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):適用於多值的毫秒類型的響應頭
    案例:
    > 發送302,設置Location頭,完成重定向!
    > 定時刷新:設置Refresh頭,你可以把它理解成,定時重定向!
    > 禁用瀏覽器緩存:Cache-Control、pragma、expires
    > <meta>標籤可以代替響應頭:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  * 響應體:通常是html、也可以是圖片!
    > response的兩個流:
      <> ServletOutputStream,用來向客戶端發送字節數據。ServletOutputStream out = resopnse.getOutputStream();
      <> PrintWriter,用來向客戶端發送字符數據!需要設置編碼。PrintWriter writer = response.getWriter();
      <> 兩個流不能同時使用!
    案例:
    > 使用PrintWriter發送字符數據
    > 使用ServletOutputStream發送字節數據(圖片)
  * 重定向:設置302,設置Location!其中變化的只有Location,所以java提供了一個快捷方法,完成重定向!
   > sendRedirect(String location)方法

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():獲取所有請求參數,其中key爲參數名,value爲參數值。
    案例:超鏈接參數
    案例:表單數據

  * 請求轉發和請求包含
    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)。
2. 請求編碼
  * 客戶端發送給服務器的請求參數是什麼編碼:
    客戶端首先要打開一個頁面,然後在頁面中提交表單或點擊超鏈接!在請求這個頁面時,服務器響應的編碼是什麼,那麼客戶端發送請求時的編碼就是什麼。
  * 服務器端默認使用什麼編碼來解碼參數:
    服務器端默認使用ISO-8859-1來解碼!所以這一定會出現亂碼的!因爲iso不支持中文!
  * 請求編碼處理分爲兩種:GET和POST:GET請求參數不在請求體中,而POST請求參數在請求體中,所以它們的處理方式是不同的!
  * GET請求編碼處理:
    > String username = new String(request.getParameter("iso-8859-1"), "utf-8");
    > 在server.xml中配置URIEncoding=utf-8
  * POST請求編碼處理:
    > String username = new String(request.getParameter("iso-8859-1"), "utf-8");
    > 在獲取參數之前調用request.setCharacterEncoding("utf-8");

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來編碼!今天不行,因爲html中不能給出java代碼,但後面學了jsp就可以了。

路徑

  * web.xml中<url-pattern>路徑,(叫它Servlet路徑!)
    > 要麼以“*”開關,要麼爲“/”開頭
  * 轉發和包含路徑
    > *****以“/”開頭:相對當前項目路徑,例如:http://localhost:8080/項目名/ request.getRequestdispacher("/BServlet").for...();
    > 不以“/”開頭:相對當前Servlet路徑。 request.getRequestdispacher("/BServlet").for...();,假如當前Servlet是:http://localhost:8080/項目名/servlet/AServlet, 就是http://localhost:8080/項目名/servlet/BServlet
  * 重定向路徑(客戶端路徑)
    > 以“/”開頭:相對當前主機,例如:http://localhost:8080/, 所以需要自己手動添加項目名,例如;response.sendRedirect("/day10_1/Bservlet");
  * 頁面中超鏈接和表單路徑
    > 與重定向相同,都是客戶端路徑!需要添加項目名
	> <form action="/day10_1/AServlet">
	> <a href="/day10_/AServlet">
	> <a href="AServlet">,如果不以“/”開頭,那麼相對當前頁面所在路徑。如果是http://localhost:8080/day10_1/html/form.html。 即:http://localhost:8080/day10_1/html/ASevlet
	> *****建立使用以“/”開頭的路徑,即絕對路徑!
  * ServletContext獲取資源路徑
    > 相對當前項目目錄,即當然index.jsp所在目錄
  * ClassLoader獲取資源路徑
    > 相對classes目錄
  * Class獲取資源路徑
    > 以“/”開頭相對classes目錄
    > 不以“/”開頭相對當前.class文件所在目錄。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章