Servlet詳解(二):request和response對象

什麼是request和response

request對象是服務器對瀏覽器請求的封裝,而response是服務器對服務器響應的封裝。
這裏寫圖片描述

request用來取出請求信息,而response則用來添加要返回給瀏覽器的信息。

使用response對象設置http響應協議中的信息

用來生成Http響應信息,發送給用戶。

響應首行

HTTP/1.1 200 OK

  • setStatus(int sc):設置正常的響應狀態碼 status code
  • setStatus(int sc, String sm):設置正常的響應狀態碼,狀態碼描述 status message,過時,因爲正常狀態下,狀態碼信息不會顯示給用戶,所以沒有必要設置
  • sendError(int sc):設置錯誤的狀態碼
  • sendError(int sc, String sm):設置錯誤的狀態碼,包含錯誤信息

響應頭

key:value

  • setHeader(String name, String value):設置一個鍵值對,值爲string
  • setDateHeader(String name, long date):設置一個鍵值對,值爲long,long常用於毫秒的表示
  • setIntHeader(String name, int value):設置一個鍵值對,值爲int類型
  • setHeader(String name, String value):添加一個鍵值對,值爲string
  • setDateHeader(String name, long date):添加一個鍵值對,值爲long,long常用於毫秒的表示
  • setIntHeader(String name, int value):添加一個鍵值對,值爲int類型
  • add 和 set 區別在於,前置直接添加(key是可以重複的),後者會修改原來的,沒有才會添加。

幾個常見的響應頭:

  • ContentType:text/html;charset=utf-8
  • Refresh:3;url=http://path 3秒後跳轉網頁

html中meta標籤的作用就是用於向響應頭中添加信息。

響應空行

一個分隔符

響應正文

需要發送的資源

  • response.getWriter():獲取字符流
  • 父類方法getOutputSteam():獲取輸出字節流

實現請求重定向

手動實現:

實現重定向很簡單,只需要兩個步驟:

  1. 在響應頭中添加302狀態碼,告訴瀏覽器需要進行重定向
    response.setStatus(302)

  2. 在響應頭中添加Location,指定重定向的位置
    response.setHeader("Location", "http://www.baidu.com");

當用戶請求servlet時,服務器返回一個類似上面的響應頭,上面的信息告訴瀏覽器,應該重新進行一次請求,請求的地址爲 Header中的Location地址。
所以,請求重定向實際上是兩次請求。

直接實現:

我們只需要使用:response.setRedirect("http://www.baidu.com")即可實現。

通過訪問Servlet向瀏覽器傳遞一個圖片

// 獲取圖片輸入流
InputStream is = getServletContext().getResourceAsStream("/WEB-INFO/mm.jpg");
// 獲取瀏覽器的輸出流
byte[] buffer = new byte[1024];
// 將圖片篇輸入流寫出到瀏覽器中
int len = -1;
while((len = is.readBuffer(buffer)) != -1){
    os.write(buffer, 0, len);
    os.flush();
}

通過訪問Servlet下載文件

類似於圖片,但是瀏覽器不能識別文件的名稱和文件的類型,需要我們在響應頭中設置文件的類型:

ServletContext sc = getServletContext();
String mimeType = sc.getMimeType("下載的文件名稱"); // 傳入下載的文件名稱,會根據名稱的拓展名識別mime類型
response.setContentType(type);

即可。

通過request對象獲取http請求協議中的內容

用來生成http請求信息。

請求首行

請求方式 請求路徑 協議/版本號

  • request.getMethod() 請求方式
  • request.getContextPath()getServletPath()…獲取請求路徑
  • 父類方法 request.getScheme() 獲取請求協議

請求頭

鍵值對

  • request.getHeader(String name)
  • request.getIntHeader(String name)
  • request.getDateHeader(String name)
  • request.getHeaderNames()
  • request.getHeaders(Sring name)一個key對應多個value

請求空行

請求正文(post纔有)

但是以下方法,無論是get還是post請求都可以獲得參數值

  • 父類方法 String getParameter(String name)
  • Map<String, String[]> getParameterMap()
  • Enumeration getParameterNames()
  • String[] getParameterValues(String name)

解決響應和請求的亂碼問題

處理get請求編碼問題

解決方案:在conf/server.xml中URIEncoding="UTF-8" 69行,

<Connector URIEncoding="UTF-8" 
    connectionTimeout="20000" 
    port="8888" 
    protocol="HTTP/1.1" 
    redirectPort="8443"/>

設置URIEncoding爲UTF-8

處理post請求編碼問題

服務器響應時的數據,即服務器向瀏覽器傳遞的數據的編碼格式由服務器決定:
編碼時使用的編碼表,使用getByte("編碼表")設置,或者使用response.setCharacterEncoding(編碼表)設置。兩者的區別在於 ,前者設置字節流碼錶,後者設置字符流碼錶。

解碼時使用的編碼表,使response.setHeader("ContentType","text/html;charset=utf-8")指定http響應頭來設置。

這裏寫圖片描述


客戶端發送請求時的亂碼解決:
GET提交,參數在URL中,設置URL的解碼配置,服務器默認使用IOS-8855-1拉丁碼錶解碼URL,我們可以通過 tomcat/config/server.xml配置文件中:

 <Connector 
     connectionTimeout="20000" 
     port="8080" 
     protocol="HTTP/1.1" 
     redirectPort="8443"/>

添加屬性URIEncoding="UTF-8"即可將服務器默認的解碼url的方式設置爲utf-8

或者在doget方法中

將接收的亂碼文字使用新的碼錶轉換:

String name = request.getParamter("name"); // 獲取亂碼文字
byte[] bs = name.getBytes("IOS-8859-1"); // 根據亂碼碼錶,將文字轉換爲字節數組
    String s = new String(bs, "UTF-8"); // 將字節數組按照新的碼錶解碼,生成文字

這裏寫圖片描述

POST提交

與GET提交解碼的區別:
解碼事件不同,GET因爲參數在URL中,所以服務器一旦接受請求就會立刻解碼參數,而POST在Servlet調用獲取參數的方法時纔會解碼。
所以,解決post請求的亂碼很簡單,只需要在參數調用前使用

request.setCharacterEncoding("utf-8");

設置請求解碼錶即可。

request 請求轉發實現和request域

這裏寫圖片描述

這就是請求轉發,瀏覽器發送請求,servlet處理request和response部分業務,但是無法全部處理,也無法簡單的顯示到頁面中,所以將處理過得request和response發送給jsp,jsp進行一些業務操作,並響應給瀏覽器,展示。

請求轉發主要用來分工操作。

AServlet doGet():


// ***** 不標準自定義轉發
//todo AServlet進行業務處理,比如從數據庫獲取數據
// 處理結束後:=>
// 發送給Bservlet
BServlet bServlet = new BServlet();
bServlet.doGet(request, response);

//*****標準轉發
// 使用request域(一個請求內有效,主要用於請求轉發) 保存數據庫的信息,發送給BServlet,即 AServlet和BServlet使用request域共享數據,request域是request對象中的一個Map。
request.setAttribute("name","Feathers");  // 向request域中存入一個鍵值對
request.getRequestDispatcher("/servlet/BServlet").forword(request.response);

BServlet doGet():

// todo 負責輸出顯示
// 從request域中取出值
System.out.println((String)request.getAttribute("name"));

注意:

不能在轉發的Servlet中向瀏覽器輸出任何響應正文的內容,但是可以添加響應頭。
因爲Servlet中,即使你添加了響應體,也會被清空。

重定向和轉發的區別

  • 重定向是一次請求,轉發一次請求
  • 重定向可以訪問項目之外的地址,而轉發不能。
  • 重定向不可以使用request域,而轉使用request域,一次請求,一個request對象
  • 重定向地址欄可能會發生會發生變化,而轉發一定不會
  • 重定向請求方式有可能發生改變(重定後的請求一定是get請求,只有顯示設置post纔是post請求,否則是get請求),而轉發不會
  • 重定向時response的方法(通過修改response頭來完成重定向),而請求轉發是resquest的方法(一次請求,轉發給不同的Servlet)

請求包含

請求轉發,轉發的Servlet不能修改請求體,而請求包含中,同請求轉發類似,但是可以修改請求體。
用途:用來解決重複操作。
將重複的操作提取到這個Servlet中,統一進行處理。

這裏寫圖片描述

往往在多個JSP中使用,一個jsp用於處理相同的操作,其餘的jsp根據是否需要處理,進行依次處理。

實現:
AServlet doGet():

response.setContentType("text/html;charset=utf-8");
// 包含
request.getRequestDispatcher("/servlet/BServlet").include(request,response);
response.getWriter().write("Aservlet 處理");

BServlet doGet():

response.getWriter().write("Bservlet 處理");

結果:

Aservlet 處理Bservlet 處理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章