(JavaEE-05)Response與Request

如何纔算掌握Servlet

  • ServletConfig
  • ServletContext
  • Request
  • Response
  • Cookie
  • Session

上面這些對象(固然不止這些,剩下的對象查閱ServletAPI,不是JavaEEAPI)都是web服務器在條用Servlet時所建立的交給Servlet的對象,將這些對象的API掌握熟練,就基本上掌握Servlet技術了,剩下的就是你的Java編程功力了,基本都是設計方面的事了。html

Web服務器

web服務器接受到客戶端的http請求,會針對每一次請求,分別建立一個用於表明請求的request對象和表明相應的response對象。若是須要獲取客戶端的相關信息,就使用request對象,須要向客戶端發送數據,就使用response對象java

這裏的request對象和response對象都不是標準的HTTP協議的請求和響應,而是Web服務器根據標準的HTTP協議的請求和響應,而後再根據Servlet規範(接口)實現的Web對象。web

###Servlet技術 其實Servlet技術就是一套接口,這個接口是由當年的SUN公司指定的,Tomcat是一個web服務器,也是Servlet和JSP的容器,爲何它是Servlet與JSP的容器呢,緣由就是它實現了SUN規定的那一套關於Servlet和JSP的規範與接口,因此在查閱ServletAPI時你會發現,不少都是接口,這是正常的,具體的顯示類是由Tomcat來完成的,咱們只管調用。HttpServletResponse與HttpServletRequest都是接口。若是你本身編寫了一個服務器,並且實現了Servlet與JSP的接口與規範,那麼你本身編寫的這個服務器也能夠是Servlet和JSP的容器(不徹底的JAVAEE容器,由於徹底的還須要實現EJB相關接口和規範)。apache

HttpServletResponse

Response對象表明響應,一個標準的HTTP響應包含三部分:狀態行響應頭響應數據。 經常使用方法有:編程

  • setStatus(int sc),設置響應的狀態信息
  • setHeader(java.lang.String name, java.lang.String value),設置響應的頭信息
  • getWriter(),返回一個PrintWriter對象,給客戶端發送信息
  • getOutoutStream() ,返回一個ServletOutputStream對象,給客戶端發送流信息

在學習過程當中要注意,學習什麼技術就查什麼文檔,例如如今在學習JavaEE中的Servlet技術,那麼就查閱ServletAPI,不要查閱JavaEEAPI,這樣更加方便,清晰。設計模式

###ResponseAPI數組

###response常見應用瀏覽器

  • 向客戶端輸出中文數據緩存

    • OutputStream向客戶端發送中文數據(默認編碼與設定編碼的問題,亂碼的緣由:客戶端使用系統默認編碼),處理方法:設置響應頭信息
    • 使用HTML語言裏面的<meta>標籤來控制瀏覽器行爲(模擬一個http響應頭),也能夠解決亂碼問題
    • 使用OutputStream輸出數字1,應該字符化
    • 使用PrintWriter來輸出,設置response的編碼(response默認的編碼問題),還須要告訴瀏覽器(客戶端)以什麼編碼方法打開,使用response的setHeader,簡寫可使用setConteType
  • 文件下載和中文文件的下載tomcat

    • 獲取須要下載的文件、通知瀏覽器如下載的方式打開、向瀏覽器寫出數據
    • 若是下載文件的名字是中文,必須使用URL編碼來進行處理
  • 輸出隨機圖片

    • 在內存中建立一張圖片
    • 獲得圖片
    • 設置背景顏色
    • 設置圖片邊框
    • 設置圖片干擾線
    • 向圖片上寫數據
    • 把圖片發送給客戶端
    • 使用中文作驗證
    • 設置瀏覽器不要緩存圖片
  • 定時刷新網頁

    • 使用response的消息頭就可讓瀏覽器定時刷新網頁
    • 使用meta標籤模擬(<meta http-equiv='refresh' content='3;url=/webapp/index.html'>
  • 請求的重定向

    • 重定向與轉發的區別(一個向服務器發了兩次請求,一個向服務器發了一次請求)
    • 重定向發生,地址欄的地址會變化(重定向會增長服務器壓力)
    • 使用 302 狀態碼和 location 頭來完成,也可使用response的重定向跳轉方法來完成

###response的細節

  • getOutputStreamgetWriter方法分別用於獲得輸出二進制數據、輸出文本數據的ServletOutputStream和PrintWriter對象
  • 這兩個方法是互斥的,調用了其中的一個,另外一個就不能再調用
  • 在一個請求的整個調用鏈中,只能有一個流存在,若是須要寫多種數據,使用字節流來完成
  • Servlet引擎在service結束後,會自動檢測response的流是否關閉,若是沒有會自動關閉,而後再銷燬Servlet,可是本身使用的流須要本身手動關閉

#HttpServletRequest HttpServletRequest對象表明客戶端的請求,當客戶端經過HTTP協議訪問服務器時,HTTP請求頭中的全部信息都封裝在這個對象中,經過這個對象,就能夠獲取客戶端的相關信息。

####經常使用方法:

  • getRequestURL方法返回客戶端發出請求時的完整URL,資源在互聯網上的位置
  • getRequestURI方法返回請求行中的資源名部分,資源的位置
  • getQueryString 方法返回請求行中的參數部分
  • getRemoteAddr方法返回發出請求的客戶機的IP地址,屏蔽IP
  • getRemoteHost方法返回發出請求的客戶機的完整主機名,註冊DNS的主機名稱,若是沒有註冊,返回IP
  • getRemotePort方法返回客戶機所使用的網絡端口號
  • getLocalAddr方法返回WEB服務器的IP地址
  • getLocalName方法返回WEB服務器的主機名
  • getMethod獲得客戶機請求方式

####獲取客戶端請求頭:

  • getHead(name)方法
  • getHeaders(String name)方法
  • getHeaderNames方法

####獲取客戶端請求參數:

  • getParameter(name)方法
  • getParameterValues(String name)方法
  • getParameterNames方法
  • getParameterMap方法
  • getInputStream方法

###Request常見應用

####防盜鏈 防止本身網站的Web資源被別的網站使用。若是你有一個Servet,能夠返回一些Web資源(圖片、文章等等),那麼在別的網站系統中,直接使用<a>連接,或者發送一個http請求給你的Servlet應用,那麼就能獲取你網站的Web資源。

  • 使用Request對象的getHeader(「referer」)方法來獲取 referer 信息,rederer能夠告訴咱們當前這個請求是從哪一個網站點擊過來的。
  • 若是沒有使用網頁點擊,而是直接發送的http請求,那麼 rederer 的值爲null
  • 檢測 referer 的開頭是不是本站,並且不能爲 null,不然就重定向到本站首頁

####獲取各類表單輸入項的數據 若是須要向服務器發送一系列數據,可使用表單來完成。表單能夠提交表單中的表單元素(表單項)的數據到服務器,瀏覽器會把表單中的可用元素(有name屬性、disabled屬性不爲false的元素)的值封裝起來。若是表單以get方式提交,那麼這些值就會以 url 參數的形式發送給服務器,若是使用的是 post 方式提交,那麼瀏覽器會將這些數據添加到 http 請求的消息體中(負載)發送給服務器。

常見表單元素:

  • text
  • password
  • radio,若是兩個radio的name相同,就代表它們是一組,每次只會有一個被選中,默認選中使用checked = "checked"設置,使用 value 值來提交真正的數據
  • checkbox,多個值的獲取,將多選按鈕的名字都設置能同樣的,在服務端使用 getParameterValues(name)方法來獲取多個值,返回值是一個數組,使用value值來提交真正的數據
  • file
  • select,配合 option 項來提交值,select 元素來設置name,具體的值用 option來設置
  • textarea,默認值的設置不是用 value ,在標籤體中來設置
  • hidden,隱藏域

對於表單提交的數據,在服務端必定要作驗證才能使用,否則很容易發生異常

####請求數據的中文亂碼問題 在作web開發時,常常會遇到亂碼的問題,最好的解決亂碼的方式就是從一開始就統一編碼。

  • 若是出現亂碼,首先要分析出現亂碼的緣由,也就是肯定是哪個環節致使了亂碼
  • 通常常見的是:request的默認編碼是 IOS8859-1,而頁面提交的數據(頁面的編碼可使用響應頭和<meta>標籤來設置,通常推薦UTF-8)不是這個編碼。對於這種編碼通常很好解決,使用 request的 setCharacterEncoding(encoding) 方法來設置 request的編碼就能夠了,可是這種設置僅對 post 方式提交的請求有效
  • 對於以 get 方式提交的請求,在Servlet中處理的話,只能使用手動的轉碼來實現,將 ISO8859-1 轉成響應的編碼。
  • get 方式提交的請求的亂碼,還有一種方式能夠解決亂碼:改變 Tomcat 的配置(給鏈接器配置一個屬性:URIEncoding="UTF-8")。
  • 若是超連接中提交的數據包含中文,必定要進行URL編碼處理

關於get的亂碼解決還有一種方式,就是使用 useBodyEncodingForURI="true",這種配置,這個配置的意思是:URI的編碼用request實際設置的編碼,這樣配置後,request的 setCharacterEncoding(encoding) 對於get請求同樣有效了。 對於改變服務器配置來解決亂碼的方法,在實際開發中並不推薦,不要依賴服務器。

####request對象實現請求轉發 使用request也能夠實現請求的轉發,在實際開發中,使用request作請求轉發的多,通常不使用ServletContext作轉發。若是在轉發過程當中須要傳值到轉發資源,使用request的setAttribute 方法來傳值,在實際開發中,是使用 request 來進行轉發和傳值的,不使用ServletContext。由於ServletContext都整個Web應用中的Servlet共享,容易出現覆蓋的問題,而request是獨立的,不存在這個問題。 request也是一個域對象,是一個容器。

請求轉發主要用來實現MVC設計模式。在MVC設計模式中,都是使用Servletl來處理用戶請求,而且產生用戶須要查看的數據,而後轉發給jsp來顯示,轉發給jsp顯示時,會把數據存在request域裏面帶給jsp。

####request域

  • setAttribute 方法
  • getAttribute 方法
  • removeAttribute 方法
  • getAttributeNames 方法

####請求轉發中的細節 在使用轉發的時候,有些小細節要注意:

  • 若是在調用forward方法以前,在Servlet程序中寫入的部份內容已經被真正傳送到了客戶端,forward方法將拋出參數異常。(好比使用PrintWriter發送數據給客戶端,而後關閉流,而後再使用request來轉發,就會拋異常)
  • 屢次請求轉發也是不可取的,同樣會拋參數異常
  • 關閉response的流,意味着提交響應結果到客戶端,若是不關閉,就沒有提交,仍是有機會作別的響應處理的,那麼別的響應處理將會覆蓋掉以前的響應(以前的響應被清空,可是對於響應頭的設置信息,會保留下來

總結:在請求轉發的先後,都不要寫數據,寫了也沒有用!!!在Servlet中,只產生數據,可是不作輸出,輸出交給JSP(MVC)

####請求重定向和請求轉發的區別

  • 一個web資源收到客戶端請求後,通知服務器去調用另一個web資源進行處理,稱之爲請求轉發
  • 一個web資源收到客戶端請求後,通知瀏覽器去訪問另一個web資源,稱之爲請求重定向
  • RequestDispatcher.forward方法只能將請求轉發給同一個WEB應用中的組件;而HttpServletResponse.sendRedirect 方法還能夠重定向到同一個站點上的其餘應用程序中的資源,甚至是使用絕對URL重定向到其餘站點的資源
  • 若是傳遞給HttpServletResponse.sendRedirect 方法的相對URL以「/」開頭,它是相對於整個WEB站點的根目錄;若是建立RequestDispatcher對象時指定的相對URL以「/」開頭,它是相對於當前WEB應用程序的根目錄
  • 調用HttpServletResponse.sendRedirect方法重定向的訪問過程結束後,瀏覽器地址欄中顯示的URL會發生改變,由初始的URL地址變成重定向的目標URL;調用RequestDispatcher.forward 方法的請求轉發過程結束後,瀏覽器地址欄保持初始的URL地址不變
  • HttpServletResponse.sendRedirect方法對瀏覽器的請求直接做出響應,響應的結果就是告訴瀏覽器去從新發出對另一個URL的訪問請求;RequestDispatcher.forward方法在服務器端內部將請求轉發給另一個資源,瀏覽器只知道發出了請求並獲得了響應結果,並不知道在服務器程序內部發生了轉發行爲
  • RequestDispatcher.forward方法的調用者與被調用者之間共享相同的request對象和response對象,它們屬於同一個訪問請求和響應過程;而HttpServletResponse.sendRedirect方法調用者與被調用者使用各自的request對象和response對象,它們屬於兩個獨立的訪問請求和響應過程

####RequestDispatcher的include方法

  • RequestDispatcher.include方法用於將RequestDispatcher對象封裝的資源內容做爲當前響應內容的一部分包含進來,從而實現可編程的服務器端包含功能
  • 被包含的Servlet程序不能改變響應消息的狀態碼和響應頭,若是它裏面存在這樣的語句,這些語句的執行結果將被忽略

####Web工程中地址的寫法 在web開發中,常常會使用地址,如:

  • this.getServletContext().getRealPath("/")
  • request.getRequestDispatcher("/")
  • response.sendRedirect("/")
  • response.getWriter().write("<meta http-equiv='refresh' content='3;url=/'>")
  • <form aciont="/">
  • <a href="/">,<img src="">

對於這些地址,裏面均可以用"/",這些有什麼區別呢?總結:凡是給服務器用的地址,"/"表明當前web應用;凡是給瀏覽器用的地址,"/"表明網站(webapps) 還有"/"與"",前者使用在虛擬路徑或者URL地址;後者使用在硬盤地址。 使用斜槓的地址,都是絕對地址,還有一些狀況是須要相對地址的(後續課程)。

相關文章
相關標籤/搜索