request、response、編碼和路徑

1. response

response對象的功能分爲以下四種:

  • 設置響應頭信息;
  • 發送狀態碼;
  • 設置響應正文;
  • 重定向;

1.1 設置響應頭信息

response.setHeader(“content-type”, “text/html;charset=utf-8)
// 設置content-type響應頭,該頭的作用是告訴瀏覽器響應內容爲html類型,編碼爲utf-8。而且同時會設置response的字符流編碼爲utf-8,即response.setCharaceterEncoding(“utf-8”);
response.setHeader("Refresh","5; URL=http://www.itcast.cn")
// 5秒後自動跳轉到傳智主頁

1.2 發送狀態碼及其他方法

response.setContentType("text/html;charset=utf-8"):等同與調用response.setHeader(“content-type”, “text/html;charset=utf-8);
response.setCharacterEncoding(“utf-8):設置字符響應流的字符編碼爲utf-8; 
response.setStatus(200):設置狀態碼;
response.sendError(404, “您要查找的資源不存在”):當發送錯誤狀態碼時,Tomcat會跳轉到固定的錯誤頁面去,但可以顯示錯誤信息。

1.3 設置響應正文

response是響應對象,向客戶端輸出響應正文(響應體)可以使用response的響應流,repsonse一共提供了兩個響應流對象:

PrintWriter out = response.getWriter():獲取字符流對象;
ServletOutputStream out = response.getOutputStream():獲取字節流對象;

response.getWriter()是PrintWriter類型,所以它有緩衝區,緩衝區的默認大小爲8KB。
如果希望響應數據馬上發送給客戶端,需要調用response.flushBuffer()方法來手動刷新緩衝區;

1.4 重定向

  • 重定向是兩次請求;
  • 重定向的URL可以是其他應用,不侷限於當前應用;
  • 重定向的響應頭爲302,並且必須要有Location響應頭;
  • 重定向就不要再使用response.getWriter()或response.getOutputStream()輸出數據,不然可能會出現異常;

2. request

在這裏插入圖片描述
request的功能:

  • 封裝了請求頭數據;
  • 封裝了請求正文數據,如果是GET請求,那麼就沒有正文;
  • request是一個域對象,可以把它當成Map來添加獲取數據;
  • request提供了請求轉發和請求包含功能。

2.1 請求頭

String getHeader(String name):獲取指定名稱的請求頭;
Enumeration getHeaderNames():獲取所有請求頭名稱;
int getIntHeader(String name):獲取值爲int類型的請求頭。

加粗樣式

2.2 請求參數

String getParameter(String name):通過指定名稱獲取參數值;
String[] getParameterValues(String name):當多個參數名稱相同時,可以使用方法來獲取;
Enumeration getParameterNames():獲取所有參數的名字;
Map getParameterMap():獲取所有參數封裝到Map中,其中key爲參數名,value爲參數。

2.3 域對象

request是域對象!一個請求只會創建一個request對象。
Servlet中三大域對象:request、session、application。

void setAttribute(String name, Object value)
Object getAttribute(String name)
void removeAttribute(String name)
Enumeration getAttributeNames()

2.4 請求轉發和請求包含

(1)一個請求跨多個Servlet,需要使用轉發和包含。

RequestDispatcher rd = request.getRequestDispatcher("/MyServlet");  使用request獲取RequestDispatcher對象,方法的參數是被轉發或包含的Servlet的Servlet路徑
請求轉發:rd.forward(request,response);
請求包含:rd.include(request,response);
  • 請求轉發:由下一個Servlet完成響應體!當前Servlet可以設置響應頭!(留頭不留體)
  • 請求包含:由兩個Servlet共同完成響應體!(都留)
  • 無論是請求轉發還是請求包含,都在一個請求範圍內!使用同一個request和response

(2)請求轉發與請求包含比較

  • 轉發留頭不留體,包含都可以留;
  • 請求包含大多是應用在JSP頁面中,完成多頁面的合併;
  • 請求轉發大多是應用在Servlet中,轉發目標大多是JSP頁面;

(3)請求轉發與重定向比較

  • 請求轉發是一個請求,而重定向是兩個請求
  • 請求轉發後瀏覽器地址欄不會有變化,而重定向會有變化,因爲重定向是兩個請求;
  • 請求轉發的目標只能是本應用中的資源,重定向的目標可以是其他應用;
  • 請求轉發對AServlet和BServlet的請求方法是相同的,即要麼都是GET,要麼都是POST,因爲請求轉發是一個請求;
  • 重定向的第二個請求一定是GET;
  • 請求轉發是服務器端行爲,只需給出轉發的Servlet路徑,而重定向需要給出requestURI,即包含項目名!
  • 請求轉發和重定向效率是轉發高!因爲是一個請求!
  • 需要在下一個Servlet中獲取request域中的數據,必須要使用轉發!

3.編碼

3.1 請求編碼

在這裏插入圖片描述

  • 直接在地址欄給出請求
    不同瀏覽器使用不同的編碼,所以這是不確定的!IE和FireFox:使用GB2312;而Chrome:使用UTF-8;

  • 在頁面發出請求
    頁面是服務器發送到客戶端瀏覽器的,所以這個頁面本身的編碼由服務器決定。

<head>
    <title>index.html</title>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  • get請求解讀編碼
    request.getParameter()獲取的數據是被服務器誤認爲ISO-8859-1編碼的,所以需要使用ISO-8859-1解碼再編碼成需要的格式。
String name = request.getParameter(“name”);
name = new String(name.getBytes(“iso-8859-1), “utf-8);
  • post請求解讀編碼
    (1)先指定編碼:request.setCharacterEncoding();再讀取數據:reuqest.getParameter()
    (1)但如果沒有指定編碼,那麼默認還是使用ISO-8859-1來解讀。
request.setCharacterEncoding(“utf-8);
String name = request.getParameter(“name”);

3.2 響應編碼

在這裏插入圖片描述
服務器默認的相應編碼是ISO-8859-1,使用response.getWriter()發送數據之前,一定要設置response的編碼:

response.setCharacterEncoding(“utf-8);

同時需要通知瀏覽器使用的解碼方式:

response.setContentType(“text/html;charset=utf-8);

在靜態頁面中,使用<meta>來設置content-type響應頭,例如:

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

3.3 URL編碼

特殊字符需要先轉換成URL編碼格式,再發送給服務器。
表單自動使用URL編碼,只有get請求需要手動設置編碼:
這裏使用JS修改:

 <script type="text/javascript">
 	function _go() {
 		location = "/day05_2/AServlet?name=" + encodeURIComponent("傳智+播客");
 	}
 </script>
<a href="javascript:_go();">鏈接</a>

4.路徑問題

4.1. 客戶端路徑和服務器端路徑

  • 客戶端路徑需要給出應用名稱,例如:/day05_1/AServlet
  • 服務器端路徑無需給出應用名稱,例如:/AServlet

4.2. 客戶端路徑

1). 頁面中都是客戶端路徑:

  • <a>的href:如果不以“/”開頭,那麼相對當前.html頁面所在路徑
  • <form>的action
  • <img>的src

2). 重定向也是客戶端路徑:
以“/”開頭:相對當前主機,例如:http://localhost:8080/,所以需要自己手動添加項目名

response.sendRedirect("/day05_1/BServlet");
相當於:http://localhost:8080/day05_1/BServlet

4.3. 服務器端路徑

(1)<url-pattern>:也叫Servlet路徑

  • 要麼以“*”開關,要麼爲“/”開頭

(2)請求轉發和請求包含

  • 以“/”開頭:相對當前項目路徑,例如:http://localhost:8080/項目名/
request.getRequestdispacher("/BServlet")
==>文件地址 http://localhost:8080/項目名/BServlet.java 
  • 不以“/”開頭:相對當前Servlet路徑。
- request.getRequestdispacher("/BServlet");

假如當前Servlet是:http://localhost:8080/項目名/servlet/AServlet,
就是http://localhost:8080/項目名/servlet/BServlet

(3)ServletContext獲取資源等
相對當前項目目錄,即當然index.jsp所在目錄(http://localhost:8080/項目名)

4.4 獲取類路徑資源

可以通過Class類的對象來獲取類路徑下的資源,對應JavaWeb應用的類路徑就是classes目錄下的資源。
類路徑對一個JavaWeb項目而言,就是/WEB-INF/classes和/WEB-INF/lib/每個jar包!

常見方式

  • Class類的getResourceAsStream(String path):
    路徑以“/”開頭,相對classes路徑;
    路徑不以“/”開頭,相對當前.class文件所在路徑,例如在cn.itcast.servlet.MyServlet中執行,那麼相對/classes/cn/itcast/servlet/路徑;

  • ClassLoader類的getResourceAsStream(String path):
    相對classes路徑;

例如
在這裏插入圖片描述

InputStream in = this.getClass().getResourceAsStream("/xxx.txt"); // 在classes文件夾內
System.out.println(IOUtils.toString(in));

InputStream in = this.getClass().getClassLoader().getResourceAsStream("xxx.txt");// 在classes文件夾
System.out.println(IOUtils.toString(in));
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章