java基礎學習:JavaWeb之request和response

其他更多java基礎文章:
java基礎學習(目錄)

學習request和response之前先學習一下http請求


HTTP請求

瀏覽器向服務器請求某個web資源時六孵,稱之為瀏覽器向服務器發(fā)送了一個http請求英融。一個完整http請求應該包含三個部分:

  • 請求行【描述客戶端的請求方式、請求的資源名稱奴迅,以及使用的HTTP協(xié)議版本號】
  • 多個消息頭【描述客戶端請求哪臺主機零截,以及客戶端的一些環(huán)境信息等】
  • 一個空行

請求行

請求行:GET /java.html HTTP/1.1
請求行中的GET稱之為請求方式炕矮,請求方式有:POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT。
常用的有:POST,GET
一般來說棍苹,當我們點擊超鏈接,通過地址欄訪問都是get請求方式茵汰。通過表單提交的數據一般是post方式枢里。
可以簡單理解GET方式用來查詢數據,POST方式用來提交數據,get的提交速度比post快
GET方式:在URL地址后附帶的參數是有限制的蹂午,其數據容量通常不能超過1K栏豺。
POST方式:可以在請求的實體內容中向服務器發(fā)送數據,傳送的數據量無限制豆胸。

請求頭

  • Accept: text/html,image/* 【瀏覽器告訴服務器奥洼,它支持的數據類型】
  • Accept-Charset: ISO-8859-1 【瀏覽器告訴服務器,它支持哪種字符集
  • Accept-Encoding: gzip,compress 【瀏覽器告訴服務器晚胡,它支持的壓縮格式
  • Accept-Language: en-us,zh-cn 【瀏覽器告訴服務器灵奖,它的語言環(huán)境】
  • Host: www.it315.org:80【瀏覽器告訴服務器,它的想訪問哪臺主機】
  • If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT【瀏覽器告訴服務器估盘,緩存數據的時間】
  • Referer: http://www.it315.org/index.jsp【瀏覽器告訴服務器瓷患,客戶機是從那個頁面來的---反盜鏈
  • 8.User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)【瀏覽器告訴服務器,瀏覽器的內核是什么】
  • Cookie【瀏覽器告訴服務器遣妥,帶來的Cookie是什么
  • Connection: close/Keep-Alive 【瀏覽器告訴服務器尉尾,請求完后是斷開鏈接還是保持鏈接】
  • Date: Tue, 11 Jul 2000 18:23:51 GMT【瀏覽器告訴服務器,請求的時間】

HTTP響應

一個HTTP響應代表著服務器向瀏覽器回送數據燥透,一個完整的HTTP響應應該包含四個部分:

  1. 一個狀態(tài)行【用于描述服務器對請求的處理結果沙咏。
  2. 多個消息頭【用于描述服務器的基本信息,以及數據的描述班套,服務器通過這些數據的描述信息肢藐,可以通知客戶端如何處理等一會兒它回送的數據
  3. 一個空行
  4. 實體內容【服務器向客戶端回送的數據

狀態(tài)行

格式: HTTP版本號 狀態(tài)碼 原因敘述
狀態(tài)行:HTTP/1.1 200 OK
狀態(tài)碼用于表示服務器對請求的處理結果,它是一個三位的十進制數吱韭。響應狀態(tài)碼分為5類

image.png

響應頭

  • Location: http://www.it315.org/index.jsp 【服務器告訴瀏覽器要跳轉到哪個頁面
  • Server:apache tomcat【服務器告訴瀏覽器吆豹,服務器的型號是什么】
  • Content-Encoding: gzip 【服務器告訴瀏覽器數據壓縮的格式
  • Content-Length: 80 【服務器告訴瀏覽器回送數據的長度】
  • Content-Language: zh-cn 【服務器告訴瀏覽器鱼的,服務器的語言環(huán)境】
  • Content-Type: text/html; charset=GB2312 【服務器告訴瀏覽器,回送數據的類型
  • Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT【服務器告訴瀏覽器該資源上次更新時間】
  • Refresh: 1;url=http://www.it315.org【服務器告訴瀏覽器要定時刷新
  • Content-Disposition: attachment; filename=aaa.zip【服務器告訴瀏覽器以下載方式打開數據
  • Transfer-Encoding: chunked 【服務器告訴瀏覽器數據以分塊方式回送】
  • Set-Cookie:SS=Q0=5Lb_nQ; path=/search【服務器告訴瀏覽器要保存Cookie
  • Expires: -1【服務器告訴瀏覽器不要設置緩存
  • Cache-Control: no-cache 【服務器告訴瀏覽器不要設置緩存
  • Pragma: no-cache 【服務器告訴瀏覽器不要設置緩存
  • Connection: close/Keep-Alive 【服務器告訴瀏覽器連接方式】
  • Date: Tue, 11 Jul 2000 18:23:51 GMT【服務器告訴瀏覽器回送數據的時間】

HttpServletRequest

概述

HttpServletRequest對象代表客戶端的請求痘煤,當客戶端通過HTTP協(xié)議訪問服務器時凑阶,HTTP請求頭中的所有信息都封裝在這個對象中,開發(fā)人員通過這個對象的方法衷快,可以獲得客戶這些信息宙橱。
request就是將請求文本封裝而成的對象,所以通過request能獲得請求文本中的所有內容蘸拔,請求頭师郑、請求體、請求行


image.png

常用方法

1. 請求頭

我們可以查看任意一個網頁调窍,它都是有請求頭的宝冕。

image

相關方法: 
String getHeader(String name)根據頭名稱得到頭信息值
long getDateHeader(java.lang.String name) 獲得指定頭內容Date
int getIntHeader(java.lang.String name) 獲得指定頭內容int
Enumeration getHeaderNames() 得到所有頭信息name
Enumeration getHeaders(String name) 根據頭名稱得到相同名稱頭信息值

Enumeration<String> headerNames = req.getHeaderNames();
        while(headerNames.hasMoreElements()){
            String key = (String)headerNames.nextElement();
            String value = req.getHeader(key);
            System.out.println(key+"="+value);
        } 
2. 請求體

1)與表單獲取相關的方法:
String getParameter(name) :根據表單中name屬性的名,獲取value屬性的值方法
String[] getParameterValues(String name):專為復選框取取提供的方法
getParameterNames():得到表單提交的所有name的方法
Map<String , String[]> getParameterMap(): 得到表單提交的所有值的方法 //做框架用邓萨,非常實用
getInputStream: 以字節(jié)流的方式得到所有表單數據

2)與操作非表單數據相關的方法(request也是一個域對象):
void setAttribute(String name, Object value);
Object getAttribute(String name);
Void removeAttribute(String name);

3)與請求轉發(fā)相關的方法: 
RequestDispatcher getRequestDispatcher(String path) //得到請求轉發(fā)或請求包含的協(xié)助對象
forward(ServletRequest request, ServletResponse response) //轉發(fā)的方法
include(ServletRequest request, ServletResponse response) //請求包含

4)與編碼相關的方法:
//解決post方式編碼
request.setCharacterEncoding("UTF-8") :告訴服務器客戶端什么編碼,只能處理post請求方式
//解決get方式編碼
String name = new String(name.getBytes(“iso-8859-1”),”UTF-8”);

3. 其他常用請求方法

getMethod();
getRequestURL();
getRequestURI();
getServerName();
getServerPort();
getContextPath();
getServletPath();
getQueryString();
getRemoteAddr();
getProtocol();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.統(tǒng)一資源標記符   /Web_Servlet/ServletTest3
        String uri = req.getRequestURI();
        System.out.println(uri);
        //2.統(tǒng)一資源定位符    http://localhost:6060/Web_Servlet/ServletTest3 
        StringBuffer url = req.getRequestURL();
        System.out.println(url);
        //3.協(xié)議和版本    HTTP/1.1
        String potocol = req.getProtocol();
        System.out.println(potocol);
        //4.協(xié)議    http
        String scheme = req.getScheme();
        System.out.println(scheme);
        //5.主機(域名)  localhost,如果你使用的是ip地址地梨,就顯示ip地址
        String serverName = req.getServerName();
        System.out.println(serverName);
        //6.端口  6060(這是我自己修改了的端口,默認是8080)
        int port = req.    getServerPort();
        System.out.println(port);
        //7.發(fā)布到tomcat下的項目名稱  /Web_Servlet
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        //8.servlet路徑    /ServletTest3 
        String servletPath = req.getServletPath();
        System.out.println(servletPath);
        //9.獲取所有請求參數缔恳,即?之后所有東西宝剖。    username=faker&password=mid
        String queryString = req.getQueryString();
        System.out.println(queryString);
        //10.遠程主機的ip地址    0:0:0:0:0:0:0:1
        String remoteAddr = req.getRemoteAddr();
        System.out.println(remoteAddr);   
    }

HttpServletResponse

概述

Web服務器收到客戶端的http請求,會針對每一次請求褐耳,分別創(chuàng)建一個用于代表請求的request對象诈闺、和代表響應的response對象。request和response對象即然代表請求和響應铃芦,那我們要獲取客戶機提交過來的數據雅镊,只需要找request對象就行了。要向容器輸出數據刃滓,只需要找response對象就行了仁烹。
HttpServletResponse對象代表服務器的響應。這個對象中封裝了向客戶端發(fā)送數據咧虎、發(fā)送響應頭卓缰,發(fā)送響應狀態(tài)碼的方法。

image

常用方法

響應行\(zhòng)響應頭\響應體

setStatus(int sc) 設置響應狀態(tài)碼
setHeader(String name, String value) 設置響應頭信息
getWrite(); 字符輸出流
getOutputStream(); 字節(jié)輸出流
setCharacterEncoding(String charset) 告知服務器使用什么編碼
setContentType(String type) 告訴響應的內容類型(text/html砰诵,application/json等)

重定向

response.sendRedirect(path);
注意:重定向沒有任何局限征唬,可以重定向web項目內的任何路徑,也可以訪問別的web項目中的路徑茁彭,并且這里就用"/"區(qū)分開來总寒,如果path使用了"/"開頭,就說明我要重新開始定位了理肺,不訪問剛才的web項目摄闸,自己寫項目名善镰,如果path沒有使用"/"開始,那么就知道是訪問剛才那個web項目下的servlet年枕,就可以省略項目名了炫欺。就是這樣來區(qū)別。

兩者的細節(jié)

兩種setCharacterEncoding

  1. request.setCharacterEncoding()指定后可以通過getParameter()則直接獲得正確的字符串熏兄,如果不指定品洛,則默認使用iso8859-1編碼。值得注意的是在執(zhí)行setCharacterEncoding()之前霍弹,不能執(zhí)行任何getParameter()毫别。而且娃弓,該指定只對POST方法有效典格,對GET方法無效。
    分析原因台丛,應該是在執(zhí)行第一個getParameter()的時候耍缴,Java將會按照編碼分析所有的提交內容,而后續(xù)的getParameter()不再進行分析挽霉,所以setCharacterEncoding()無效防嗡。而對于GET方法提交表單是,提交的內容在URL中侠坎,一開始就已經按照編碼分析提交內容蚁趁,setCharacterEncoding()自然就無效。

  2. response.setCharacterEncoding設置HTTP 響應的編碼,如果之前使用response.setContentType設置了編碼格式,則使用response.setCharacterEncoding指定的編碼格式覆蓋之前的設置.與response.setContentType相同的是,調用此方法,必須在getWriter執(zhí)行之前或者response被提交之前

學習資料:https://www.cnblogs.com/fan-xiaofan/p/6028233.html

轉發(fā)與重定向

實際發(fā)生位置不同实胸,地址欄不同

轉發(fā)是發(fā)生在服務器的:
轉發(fā)是由服務器進行跳轉的他嫡,細心的朋友會發(fā)現,在轉發(fā)的時候庐完,瀏覽器的地址欄是沒有發(fā)生變化的钢属,在我訪問Servlet111的時候,即使跳轉到了Servlet222的頁面门躯,瀏覽器的地址還是Servlet111的淆党。也就是說瀏覽器是不知道該跳轉的動作,轉發(fā)是對瀏覽器透明的讶凉。通過上面的轉發(fā)時序圖我們也可以發(fā)現染乌,實現轉發(fā)只是一次的http請求,一次轉發(fā)中request和response對象都是同一個懂讯。這也解釋了荷憋,為什么可以使用request作為域對象進行Servlet之間的通訊。

重定向是發(fā)生在瀏覽器的:
重定向是由瀏覽器進行跳轉的域醇,進行重定向跳轉的時候台谊,瀏覽器的地址會發(fā)生變化的蓉媳。曾經介紹過:實現重定向的原理是由response的狀態(tài)碼和Location頭組合而實現的。這是由瀏覽器進行的頁面跳轉實現重定向會發(fā)出兩個http請求锅铅,request域對象是無效的酪呻,因為它不是同一個request對象

用法不同

很多人都搞不清楚轉發(fā)和重定向的時候,資源地址究竟怎么寫盐须。有的時候要把應用名寫上玩荠,有的時候不用把應用名寫上。很容易把人搞暈贼邓。記住一個原則:給服務器用的直接從資源名開始寫阶冈,給瀏覽器用的要把應用名寫上

request.getRequestDispatcher("/資源名 URI").forward(request,response)
轉發(fā)時"/"代表的是本應用程序的根目錄

response.send("/web應用/資源名 URI");
重定向時"/"代表的是webapps目錄

能夠去往的URL的范圍不一樣

轉發(fā)是服務器跳轉只能去往當前web應用的資源
重定向是服務器跳轉,可以去往任何的資源

傳遞數據的類型不同

轉發(fā)的request對象可以傳遞各種類型的數據塑径,包括對象
重定向只能傳遞字符串

跳轉的時間不同

轉發(fā)時:執(zhí)行到跳轉語句時就會立刻跳轉
重定向:整個頁面執(zhí)行完之后才執(zhí)行跳轉

Servlet中亂碼解決與轉發(fā)和重定向的區(qū)別

getWriter和getOutputStream

1.選擇getOutputStream 和getWriter方法的要點

PrintWriter對象輸出字符文本內容時女坑,它內部還是將字符串轉換成了某種字符集編碼的字節(jié)數組后再進行輸出,使用PrintWriter對象的好處就是不用編程人員自己來完成字符串到字節(jié)數組的轉換统舀。
使用ServletOutputStream對象也能輸出內容全為文本字符的網頁文檔匆骗,但是,如果網頁文檔內容是在Servlet程序內部使用文本字符串動態(tài)拼湊和創(chuàng)建出來的誉简,則需要先將字符文本轉換成字節(jié)數組后輸出碉就。

2.兩種方法區(qū)別

getOutputStream方法用于返回Servlet引擎創(chuàng)建的字節(jié)輸出流對象,Servlet程序可以按字節(jié)形式輸出響應正文闷串。
getWriter方法用于返回Servlet引擎創(chuàng)建的字符輸出流對象瓮钥,Servlet程序可以按字符形式輸出響應正文。
getOutputStream和getWriter這兩個方法互相排斥烹吵,調用了其中的任何一個方法后碉熄,就不能再調用另一方法。
getOutputStream方法返回的字節(jié)輸出流對象的類型為ServletOutputStream年叮,它可以直接輸出字節(jié)數組中的二進制數據具被。
getWriter方法將Servlet引擎的數據緩沖區(qū)包裝成PrintWriter類型的字符輸出流對象后返回,PrintWriter對象可以直接輸出字符文本內容只损。
Servlet程序向ServletOutputStream或PrintWriter對象中寫入的數據將被Servlet引擎獲取一姿,Servlet引擎將這些數據當作響應消息的正文,然后再與響應狀態(tài)行和各響應頭組合后輸出到客戶端跃惫。
Serlvet的service方法結束后叮叹,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經調用過close方法,如果沒有爆存,Servlet引擎將調用close方法關閉該輸出流對象蛉顽。

3.修改編碼類型

getOutputStream解決辦法:

  1. 通過更改瀏覽器的編碼方式:IE/”查看”/”編碼”/”UTF-8”(不可取)
  2. 通過設置響應頭告知客戶端編碼方式:response.setHeader(“Content-type”, “text/html;charset=UTF-8”);//告知瀏覽器數據類型及編碼
  3. 通過meta標簽模擬請求頭:out.write("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />".getBytes());
  4. 通過以下方法:response.setContentType("text/html;charset=UTF-8");

rgetWriter解決辦法:
response. setContentType(“text/html;charset=UTF-8”);

兩者的應用

1. 文件下載
        //通過路徑得到一個輸入流
        String path = this.getServletContext().getRealPath(filepath);
        FileInputStream fis = new FileInputStream(path);
        //創(chuàng)建字節(jié)輸出流
        ServletOutputStream sos = response.getOutputStream();
        
        //得到要下載的文件名
        String filename = path.substring(path.lastIndexOf("\\")+1);
        
        //設置文件名的編碼
        filename = URLEncoder.encode(filename, "UTF-8");//將不安全的文件名改為UTF-8格式
        
        //告知客戶端要下載文件
        response.setHeader("content-disposition", "attachment;filename="+filename);
        response.setHeader("content-type", "image/jpeg");
        
        //執(zhí)行輸出操作
        int len = 1;
        byte[] b = new byte[1024];
        while((len=fis.read(b))!=-1){
            sos.write(b,0,len);
        }
        
        sos.close();
        fis.close();

2. 驗證碼
3. 定時刷新
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("3秒后跳轉頁面.....");
        //三秒后跳轉到index.jsp頁面去
        response.setHeader("Refresh", "3;url='/index.jsp'");
4. 設置緩存
        //瀏覽器有三消息頭設置緩存,為了兼容性先较!將三個消息頭都設置了
        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control","no-cache");
        response.setHeader("Pragma", "no-cache");
5. 數據壓縮
       //創(chuàng)建GZIPOutputStream對象携冤,給予它ByteArrayOutputStream
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);

        //GZIP對數據壓縮悼粮,GZIP寫入的數據是保存在byteArrayOutputStream上的
        gzipOutputStream.write("asdfzxcvasdfzxvasdfzxcv".getBytes());
        //gzipOutputStream有緩沖,把緩沖清了曾棕,并順便關閉流
        gzipOutputStream.close();

        byte[] bytes = byteArrayOutputStream.toByteArray();
        //告訴瀏覽器這是gzip壓縮的數據
        response.setHeader("Content-Encoding","gzip");
        //將壓縮的數據寫給瀏覽器
        response.getOutputStream().write(bytes);
6. 防盜鏈
        //獲取到網頁是從哪里來的
        String referer = request.getHeader("Referer");
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末扣猫,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子翘地,更是在濱河造成了極大的恐慌申尤,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衙耕,死亡現場離奇詭異昧穿,居然都是意外死亡,警方通過查閱死者的電腦和手機橙喘,發(fā)現死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門时鸵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渴杆,你說我怎么就攤上這事寥枝∠芩” “怎么了磁奖?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長某筐。 經常有香客問我比搭,道長,這世上最難降的妖魔是什么南誊? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任身诺,我火速辦了婚禮,結果婚禮上抄囚,老公的妹妹穿的比我還像新娘霉赡。我一直安慰自己,他們只是感情好幔托,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布穴亏。 她就那樣靜靜地躺著,像睡著了一般重挑。 火紅的嫁衣襯著肌膚如雪嗓化。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天谬哀,我揣著相機與錄音刺覆,去河邊找鬼。 笑死史煎,一個胖子當著我的面吹牛谦屑,可吹牛的內容都是我干的驳糯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼氢橙,長吁一口氣:“原來是場噩夢啊……” “哼结窘!你這毒婦竟也來了?” 一聲冷哼從身側響起充蓝,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤隧枫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后谓苟,有當地人在樹林里發(fā)現了一具尸體官脓,經...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年涝焙,在試婚紗的時候發(fā)現自己被綠了卑笨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡仑撞,死狀恐怖赤兴,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情隧哮,我是刑警寧澤桶良,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站沮翔,受9級特大地震影響陨帆,放射性物質發(fā)生泄漏。R本人自食惡果不足惜采蚀,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一疲牵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榆鼠,春花似錦纲爸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至责静,卻和暖如春袁滥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背灾螃。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工题翻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓嵌赠,卻偏偏與公主長得像塑荒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子姜挺,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內容