欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:Servlet中的請求與響應(yīng)

柚子快報激活碼778899分享:Servlet中的請求與響應(yīng)

http://yzkb.51969.com/

Request和Response

1.Request和Response的概述2.Request對象2.1 Request繼承體系2.2 Request獲取請求數(shù)據(jù)2.3 解決post請求亂碼問題 *2.4 Request請求轉(zhuǎn)發(fā)(-,*)2.5 request的生命周期

3.HTTP響應(yīng)詳解(理解)1.使用抓包查看響應(yīng)報文協(xié)議內(nèi)容2.HTTP響應(yīng)報文協(xié)議介紹

4.Response對象1 Response對象介紹2 Response設(shè)置響應(yīng)數(shù)據(jù)功能介紹3 Respones請求重定向4 路徑問題5 Response響應(yīng)字符數(shù)據(jù)6 Response響應(yīng)字節(jié)數(shù)據(jù)

回顧總結(jié)

1.Request和Response的概述

重點

service方法的兩個參數(shù)request和response是由tomcat創(chuàng)建的 void service(ServletRequest var1, ServletResponse var2)request 表示請求數(shù)據(jù), tomcat將瀏覽器發(fā)送過來的請求數(shù)據(jù)解析并封裝到request對象中 servlet開發(fā)者可以通過request對象獲得請求數(shù)據(jù)response 表示響應(yīng)數(shù)據(jù),服務(wù)器發(fā)送給瀏覽器的數(shù)據(jù) servlet開發(fā)者可以通過response對象設(shè)置響應(yīng)數(shù)據(jù)

==Request是請求對象,Response是響應(yīng)對象。==這兩個對象在我們使用Servlet的時候有看到:

此時,我們就需要思考一個問題request和response這兩個參數(shù)的作用是什么?

request:獲取請求數(shù)據(jù)

瀏覽器會發(fā)送HTTP請求到后臺服務(wù)器[Tomcat]HTTP的請求中會包含很多請求數(shù)據(jù)[請求行+請求頭+請求體]后臺服務(wù)器[Tomcat]會對HTTP請求中的數(shù)據(jù)進行解析并把解析結(jié)果存入到一個對象中所存入的對象即為request對象,所以我們可以從request對象中獲取請求的相關(guān)參數(shù)獲取到數(shù)據(jù)后就可以繼續(xù)后續(xù)的業(yè)務(wù),比如獲取用戶名和密碼就可以實現(xiàn)登錄操作的相關(guān)業(yè)務(wù) response:設(shè)置響應(yīng)數(shù)據(jù)

業(yè)務(wù)處理完后,后臺就需要給前端返回業(yè)務(wù)處理的結(jié)果即響應(yīng)數(shù)據(jù)把響應(yīng)數(shù)據(jù)封裝到response對象中后臺服務(wù)器[Tomcat]會解析response對象,按照[響應(yīng)行+響應(yīng)頭+響應(yīng)體]格式拼接結(jié)果瀏覽器最終解析結(jié)果,把內(nèi)容展示在瀏覽器給用戶瀏覽

對于上述所講的內(nèi)容,我們通過一個案例來初步體驗下request和response對象的使用。

@WebServlet("/demo3")

public class ServletDemo3 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//使用request對象 獲取請求數(shù)據(jù)

String name = request.getParameter("name");//url?name=zhangsan

//使用response對象 設(shè)置響應(yīng)數(shù)據(jù)

response.setHeader("content-type","text/html;charset=utf-8");

response.getWriter().write("

"+name+",歡迎您!

");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("Post...");

}

}

啟動成功后就可以通過瀏覽器來訪問,并且根據(jù)傳入?yún)?shù)的不同就可以在頁面上展示不同的內(nèi)容:

小結(jié)

我們主要認(rèn)識了下request對象和reponse對象:

request對象是用來封裝瀏覽器請求tomcat服務(wù)器數(shù)據(jù)的對象response對象是用來封裝tomcat服務(wù)器響應(yīng)給瀏覽器的數(shù)據(jù)的對象

目前我們只知道這兩個對象是用來干什么的,那么它們具體是如何實現(xiàn)的,就需要我們繼續(xù)深入的學(xué)習(xí)。接下來,就先從Request對象來學(xué)習(xí),主要學(xué)習(xí)下面這些內(nèi)容:

request繼承體系 request獲取請求參數(shù) request請求轉(zhuǎn)發(fā)(了解)

2.Request對象

2.1 Request繼承體系

在學(xué)習(xí)這節(jié)內(nèi)容之前,我們先思考一個問題,前面在介紹Request和Reponse對象的時候,比較細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn):

當(dāng)我們的Servlet類實現(xiàn)的是Servlet接口的時候,service方法中的參數(shù)是ServletRequest和ServletResponse當(dāng)我們的Servlet類繼承的是HttpServlet類的時候,doGet和doPost方法中的參數(shù)就變成HttpServletRequest和HttpServletReponse

那么,

ServletRequest和HttpServletRequest的關(guān)系是什么?request對象是有誰來創(chuàng)建的?request提供了哪些API,這些API從哪里查?

首先,我們先來看下Request的繼承體系:

ServletRequest request = new RequestFacade();

從上圖中可以看出,ServletRequest和HttpServletRequest都是Java提供的,所以我們可以打開JavaEE提供的API文檔,打開后可以看到:

所以ServletRequest和HttpServletRequest是繼承關(guān)系,并且兩個都是接口,接口是無法創(chuàng)建對象,這個時候就引發(fā)了下面這個問題:

這個時候,我們就需要用到Request繼承體系中的RequestFacade:

該類實現(xiàn)了HttpServletRequest接口,也間接實現(xiàn)了ServletRequest接口。Servlet類中的service方法、doGet方法或者是doPost方法最終都是由Web服務(wù)器[Tomcat]來調(diào)用的,所以Tomcat提供了方法參數(shù)接口的具體實現(xiàn)類,并完成了對象的創(chuàng)建要想了解RequestFacade中都提供了哪些方法,我們可以直接查看JavaEE的API文檔中關(guān)于ServletRequest和HttpServletRequest的接口文檔,因為RequestFacade實現(xiàn)了其接口就需要重寫接口中的方法

對于上述結(jié)論,要想驗證,可以編寫一個Servlet,在方法中把request對象打印下,就能看到最終的對象是不是RequestFacade,代碼如下:

@WebServlet("/demo2")

public class ServletDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println(request);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

}

}

啟動服務(wù)器,運行訪問http://localhost:8080/request-demo/demo2,得到運行結(jié)果:

小結(jié)

Request的繼承體系為ServletRequest(最大父接口)–>HttpServletRequest(可以處理http協(xié)議的請求接口)–>RequestFacade(tomcat定義的實現(xiàn)類)Tomcat需要解析請求數(shù)據(jù),封裝為request對象,并且創(chuàng)建request對象傳遞到service方法使用request對象,可以查閱JavaEE API文檔的HttpServletRequest接口中方法說明

2.2 Request獲取請求數(shù)據(jù)

HTTP請求數(shù)據(jù)總共分為三部分內(nèi)容,分別是請求行、請求頭、請求體,對于這三部分內(nèi)容的數(shù)據(jù),分別該如何獲取,首先我們先來學(xué)習(xí)請求行數(shù)據(jù)如何獲取?

2.2.1 獲取請求行數(shù)據(jù)

請求行包含三塊內(nèi)容,分別是請求方式、請求資源路徑、HTTP協(xié)議及版本

對于這三部分內(nèi)容,request對象都提供了對應(yīng)的API方法來獲取,具體如下:

獲取請求方式: GET

String getMethod()

獲取虛擬目錄(項目訪問路徑): /request-demo

String getContextPath()

獲取URL(統(tǒng)一資源定位符): http://localhost:8080/request-demo/req1

StringBuffer getRequestURL()

獲取URI(統(tǒng)一資源標(biāo)識符): /request-demo/req1

String getRequestURI()

獲取請求參數(shù)(GET方式): username=zhangsan&password=123

String getQueryString()

介紹完上述方法后,咱們通過代碼把上述方法都使用下:

/**

* request 獲取請求數(shù)據(jù)

*/

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

// String getMethod():獲取請求方式: GET

String method = req.getMethod();

System.out.println(method);//GET

// String getContextPath():獲取虛擬目錄(項目訪問路徑):/request-demo

String contextPath = req.getContextPath();

System.out.println(contextPath);

// StringBuffer getRequestURL(): 獲取URL(統(tǒng)一資源定位符):http://localhost:8080/request-demo/req1

StringBuffer url = req.getRequestURL();

System.out.println(url.toString());

// String getRequestURI():獲取URI(統(tǒng)一資源標(biāo)識符): /request-demo/req1

String uri = req.getRequestURI();

System.out.println(uri);

// String getQueryString():獲取請求參數(shù)(GET方式): username=zhangsan

String queryString = req.getQueryString();

System.out.println(queryString);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

}

啟動服務(wù)器,訪問http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,獲取的結(jié)果如下:

2.2.2 獲取請求頭數(shù)據(jù)

對于請求頭的數(shù)據(jù),格式為key: value如下:

所以根據(jù)請求頭名稱獲取對應(yīng)值的方法為:

String getHeader(String name) //參數(shù)name書寫的是請求頭冒號左邊的內(nèi)容例如:User-Agent

//User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

接下來,在代碼中如果想要獲取客戶端瀏覽器的版本信息,則可以使用

/**

* request 獲取請求數(shù)據(jù)

*/

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//獲取請求頭: user-agent: 瀏覽器的版本信息

String agent = req.getHeader("user-agent");

System.out.println(agent);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

}

重新啟動服務(wù)器后,http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,獲取的結(jié)果如下:

2.2.3 獲取請求體數(shù)據(jù)

瀏覽器在發(fā)送GET請求的時候是沒有請求體的,所以需要把請求方式變更為POST,請求體中的數(shù)據(jù)格式如下:

對于請求體中的數(shù)據(jù),Request對象提供了如下兩種方式來獲取其中的數(shù)據(jù),分別是:

獲取字節(jié)輸入流,如果前端發(fā)送的是字節(jié)數(shù)據(jù),比如傳遞的是文件數(shù)據(jù),則使用該方法

ServletInputStream getInputStream()

該方法可以獲取字節(jié)和字符數(shù)據(jù)

獲取字符輸入流,如果前端發(fā)送的是純文本數(shù)據(jù),則使用該方法

BufferedReader getReader()

接下來,大家需要思考,要想獲取到請求體的內(nèi)容該如何實現(xiàn)?

具體實現(xiàn)的步驟如下:

1.準(zhǔn)備一個頁面,在頁面中添加form表單,用來發(fā)送post請求

2.在Servlet的doPost方法中獲取請求體數(shù)據(jù)

3.在doPost方法中使用request的getReader()或者getInputStream()來獲取

4.訪問測試

在項目的webapp目錄下添加一個html頁面,名稱為:req.html

Title

在Servlet的doPost方法中獲取數(shù)據(jù)

/**

* request 獲取請求數(shù)據(jù)

*/

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//在此處獲取請求體中的數(shù)據(jù)

}

}

調(diào)用getReader()或者getInputStream()方法,因為目前前端傳遞的是純文本數(shù)據(jù),所以我們采用getReader()方法來獲取

/**

* request 獲取請求數(shù)據(jù)

*/

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//獲取post 請求體:請求參數(shù)

//1. 獲取字符輸入流

BufferedReader br = req.getReader();

//2. 讀取數(shù)據(jù)

String line = br.readLine();

System.out.println(line);

}

}

注意

BufferedReader流是通過request對象來獲取的,當(dāng)請求完成后request對象就會被銷毀,request對象被銷毀后,BufferedReader流就會自動關(guān)閉,所以此處就不需要手動關(guān)閉流了。

啟動服務(wù)器,通過瀏覽器訪問http://localhost:8080/request-demo/req.html

點擊提交按鈕后,就可以在控制臺看到前端所發(fā)送的請求數(shù)據(jù)

小結(jié)

HTTP請求數(shù)據(jù)中包含了請求行、請求頭和請求體,針對這三部分內(nèi)容,Request對象都提供了對應(yīng)的API方法來獲取對應(yīng)的值:

請求行

getMethod()獲取請求方式 GET POSTgetContextPath()獲取項目訪問虛擬路徑 /day06getRequestURL()獲取請求URL http://localhost:8080/day06/demo01getRequestURI()獲取請求URI /day06/demo01getQueryString()獲取GET請求方式的請求參數(shù),獲取的請求參數(shù)放到一個字符串中 了解 請求頭

getHeader(String name)根據(jù)請求頭名稱獲取其對應(yīng)的值 了解 請求體

注意: 瀏覽器發(fā)送的POST請求才有請求體數(shù)據(jù)如果是純文本數(shù)據(jù):getReader() 了解如果是字節(jié)數(shù)據(jù)如文件數(shù)據(jù):getInputStream()

2.2.4 獲取請求參數(shù)的通用方式(很重要)

在學(xué)習(xí)下面內(nèi)容之前,我們先提出兩個問題:

什么是請求參數(shù)?請求參數(shù)和請求數(shù)據(jù)的關(guān)系是什么?

1.什么是請求參數(shù)?

為了能更好的回答上述兩個問題,我們拿用戶登錄的例子來說明

1.1 想要登錄網(wǎng)址,需要進入登錄頁面

1.2 在登錄頁面輸入用戶名和密碼

1.3 將用戶名和密碼提交到后臺

1.4 后臺校驗用戶名和密碼是否正確

1.5 如果正確,則正常登錄,如果不正確,則提示用戶名或密碼錯誤

上述例子中,用戶名和密碼其實就是我們所說的請求參數(shù)。

get請求:請求參數(shù)位于url后面。

post請求:請求參數(shù)位于請求體中。

2.什么是請求數(shù)據(jù)?

請求數(shù)據(jù)則是包含請求行、請求頭和請求體的所有數(shù)據(jù)

3.請求參數(shù)和請求數(shù)據(jù)的關(guān)系是什么?

3.1 請求參數(shù)是請求數(shù)據(jù)中的部分內(nèi)容

3.2 如果是GET請求,請求參數(shù)在請求行中

3.3 如果是POST請求,請求參數(shù)一般在請求體中

對于請求參數(shù)的獲取,常用的有以下兩種:

GET方式:

String getQueryString()

POST方式:

BufferedReader getReader();

有了上述的知識儲備,我們來實現(xiàn)一個案例需求:

(1)發(fā)送一個GET請求并攜帶用戶名,后臺接收后打印到控制臺

(2)發(fā)送一個POST請求并攜帶用戶名,后臺接收后打印到控制臺

此處大家需要注意的是GET請求和POST請求接收參數(shù)的方式不一樣,具體實現(xiàn)的代碼如下:

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

String result = req.getQueryString();

System.out.println(result);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

BufferedReader br = req.getReader();

String result = br.readLine();

System.out.println(result);

}

}

GET請求和POST請求獲取請求參數(shù)的方式不一樣,在獲取請求參數(shù)這塊該如何實現(xiàn)呢?

要想實現(xiàn),我們就需要思考:

GET請求方式和POST請求方式區(qū)別主要在于獲取請求參數(shù)的方式不一樣,是否可以提供一種統(tǒng)一獲取請求參數(shù)的方式,從而統(tǒng)一doGet和doPost方法內(nèi)的代碼?

解決方案一:

@WebServlet("/req1")

public class RequestDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//獲取請求方式

String method = req.getMethod();

//獲取請求參數(shù)

String params = "";

if("GET".equals(method)){

params = req.getQueryString();

}else if("POST".equals(method)){

BufferedReader reader = req.getReader();

params = reader.readLine();

}

//將請求參數(shù)進行打印控制臺

System.out.println(params);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

this.doGet(req,resp);

}

}

使用request的getMethod()來獲取請求方式,根據(jù)請求方式的不同分別獲取請求參數(shù)值,這樣就可以解決上述問題,但是以后每個Servlet都需要這樣寫代碼,實現(xiàn)起來比較麻煩,這種方案我們不采用

解決方案二:

request對象已經(jīng)將上述獲取請求參數(shù)的方法進行了封裝,并且request提供的方法實現(xiàn)的功能更強大,以后只需要調(diào)用request提供的方法即可,在request的方法中都實現(xiàn)了哪些操作?

(1)根據(jù)不同的請求方式獲取請求參數(shù),獲取的內(nèi)容如下:

(2)把獲取到的內(nèi)容進行分割,內(nèi)容如下:

(3)把分割后端數(shù)據(jù),存入到一個Map集合中:

注意:因為參數(shù)的值可能是一個,也可能有多個,所以Map的值的類型為String數(shù)組。

基于上述理論,request對象為我們提供了如下方法:

獲取所有參數(shù)Map集合

Map getParameterMap()

根據(jù)名稱獲取參數(shù)值(數(shù)組)

String[] getParameterValues(String name)參數(shù)name是前端提交請求參數(shù)的等號左邊的key(name)==>username=zhangsan===>想獲取zhangsan===>getParameterValues("username");

根據(jù)名稱獲取參數(shù)值(單個值)

String getParameter(String name)注意:如果參數(shù)的name有多個值誰在前面先獲取誰

接下來,我們通過案例來把上述的三個方法進行實例演示:

1.修改req.html頁面,添加愛好選項,愛好可以同時選多個

Title



游泳

爬山

2.在Servlet代碼中獲取頁面?zhèn)鬟fGET請求的參數(shù)值

2.1獲取GET方式的所有請求參數(shù)

/**

* request 通用方式獲取請求參數(shù)

*/

@WebServlet("/req2")

public class RequestDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//GET請求邏輯

System.out.println("get....");

//1. 獲取所有參數(shù)的Map集合

Map map = req.getParameterMap();

for (String key : map.keySet()) {

// username:zhangsan lisi

System.out.print(key+":");

//獲取值

String[] values = map.get(key);

for (String value : values) {

System.out.print(value + " ");

}

System.out.println();

}

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

}

獲取的結(jié)果為:

2.2獲取GET請求參數(shù)中的愛好,結(jié)果是數(shù)組值

/**

* request 通用方式獲取請求參數(shù)

*/

@WebServlet("/req2")

public class RequestDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//GET請求邏輯

//...

System.out.println("------------");

String[] hobbies = req.getParameterValues("hobby");

for (String hobby : hobbies) {

System.out.println(hobby);

}

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

}

獲取的結(jié)果為:

2.3獲取GET請求參數(shù)中的用戶名和密碼,結(jié)果是單個值

/**

* request 通用方式獲取請求參數(shù)

*/

@WebServlet("/req2")

public class RequestDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//GET請求邏輯

//...

String username = req.getParameter("username");

String password = req.getParameter("password");

System.out.println(username);

System.out.println(password);

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

}

獲取的結(jié)果為:

3.在Servlet代碼中獲取頁面?zhèn)鬟fPOST請求的參數(shù)值

3.1將req.html頁面form表單的提交方式改成post

3.2將doGet方法中的內(nèi)容復(fù)制到doPost方法中即可

小結(jié)

req.getParameter()和getParameterMap()方法使用的頻率會比較高

2.3 解決post請求亂碼問題 *

學(xué)習(xí)目標(biāo)

能夠掌握產(chǎn)生亂碼的原因以及如何解決post亂碼

內(nèi)容講解

html頁面:

Title


【1】從tomcat8開始以后,對于get請求亂碼,tomcat已經(jīng)解決。對于post請求中文亂碼沒有解決,需要我們自己處理。

【2】post請求亂碼產(chǎn)生的原因和解決思路

說明:

1)頁面使用的編碼表是UTF-8編碼,tomcat使用的是默認(rèn)編碼表ISO-8859-1進行解碼,編碼和解碼使用的編碼表不一致導(dǎo)致亂碼。

2)解決思路:先按照ISO-8859-1編碼,在按照UTF-8進行重新解碼

【3】解決方案

解決方案有三種:

1.方案一

【1】方式一

使用URLEncoder類進行編碼:static String encode(String s, String enc)

參數(shù):

s:編碼的字符串

enc:使用編碼表

使用URLDecoder進行解碼:static String decode(String s, String enc)

參數(shù):

s:解碼的字符串

enc:使用編碼表

2.方案二

【2】方式二:

使用String類中的方法進行編碼: byte[] getBytes(String charsetName)

參數(shù)表示指定的編碼表,返回值表示編碼后的字節(jié)數(shù)組

使用String類中的構(gòu)造方法進行解碼:String(byte[] bytes, String charsetName)

參數(shù):

bytes:字節(jié)數(shù)組

charsetName:表示指定的編碼表

返回值:解碼后的字符串

3.方案三

【3】方式三:

如果是get請求,tomcat8底層已經(jīng)幫助我們解決完了,我們只需要解決post亂碼即可,但是上述

兩種方式對于post請求可以解決亂碼,對于get請求本身獲取到的已經(jīng)是正確的數(shù)據(jù),處理

后又亂碼了。

我們的想法是:get請求不用我們自己書寫代碼處理亂碼,只需要我們書寫代碼處理post亂碼。

我們接下來學(xué)習(xí)第三種解決方案:

只解決來自于請求體數(shù)據(jù)的亂碼。而get請求體沒有數(shù)據(jù),post請求體含有數(shù)據(jù),所以我們可以理解為第三種處理方案只 是用來解決post亂碼的。使用的api是ServletRequest接口中的:

void setCharacterEncoding(String env)

參數(shù):指定的編碼表

注意:該方式的代碼必須書寫在獲取請求數(shù)據(jù)之前

【4】代碼實現(xiàn)

package com.example.sh.web;

import com.example.sh.pojo.User;

import com.example.sh.service.UserServcie;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.net.URLDecoder;

import java.net.URLEncoder;

@WebServlet("/httpServletRequestDemo04Servlet")

public class LoginServlet extends HttpServlet {

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1.獲取瀏覽器的請求數(shù)據(jù)

// String username = request.getParameter("username");

/*

解決post亂碼問題有三種方式:

【1】方式一

使用URLEncoder類進行編碼:static String encode(String s, String enc)

參數(shù):

s:編碼的字符串

enc:使用編碼表

使用URLDecoder進行解碼:static String decode(String s, String enc)

參數(shù):

s:解碼的字符串

enc:使用編碼表

*/

//1)編碼 : 使用URLEncoder類進行編碼:static String encode(String s, String enc)

// String encodeUsername = URLEncoder.encode(username, "ISO-8859-1");

// //2)解碼:使用URLDecoder進行解碼:static String decode(String s, String enc)

// username = URLDecoder.decode(encodeUsername, "UTF-8");

/*

解決post亂碼問題有三種方式:

【2】方式二:

使用String類中的方法進行編碼: byte[] getBytes(String charsetName)

參數(shù)表示指定的編碼表,返回值表示編碼后的字節(jié)數(shù)組

使用String類中的構(gòu)造方法進行解碼:String(byte[] bytes, String charsetName)

參數(shù):

bytes:字節(jié)數(shù)組

charsetName:表示指定的編碼表

返回值:解碼后的字符串

*/

//1)編碼 : 使用String類中的方法進行編碼: byte[] getBytes(String charsetName)

// byte[] bytes = username.getBytes("ISO-8859-1");

// //2)解碼:使用String類中的構(gòu)造方法進行解碼:String(byte[] bytes, String charsetName)

// username = new String(bytes, "UTF-8");

//username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

/*

解決post亂碼問題有三種方式:

【3】方式三:

如果是get請求,tomcat8底層已經(jīng)幫助我們解決完了,我們只需要解決post亂碼即可,但是上述

兩種方式對于post請求可以解決亂碼,對于get請求本身獲取到的已經(jīng)是正確的數(shù)據(jù),處理

后又亂碼了。

我們的想法是:get請求不用我們自己書寫代碼處理亂碼,只需要我們書寫代碼處理post亂碼。

我們接下來學(xué)習(xí)第三種解決方案:

只解決來自于請求體數(shù)據(jù)的亂碼。而get請求體沒有數(shù)據(jù),post請求體含有數(shù)據(jù),所以我們可以理解為第三種處理方案只是用來解決

post亂碼的。使用的api是ServletRequest接口中的:

void setCharacterEncoding(String env)

參數(shù):指定的編碼表

注意:該方式的代碼必須書寫在獲取請求數(shù)據(jù)之前

*/

request.setCharacterEncoding("utf-8");//告知tomcat使用UTF-8解碼頁面請求數(shù)據(jù)

// 1.獲取瀏覽器的請求數(shù)據(jù)

String username = request.getParameter("username");

System.out.println("username = " + username);

}

}

內(nèi)容小結(jié)

1.tomcat8以后對于get請求亂碼已經(jīng)處理完畢,我們只需要處理post請求

2.處理post請求亂碼有三種方式:

方式一:

/*

解決post請求亂碼實現(xiàn):

方式一:

編碼:URLEncoder:HTML 格式編碼的實用工具類。編碼方法:

static String encode(String s, String enc) 參數(shù):s 編碼的字符串 enc 編碼使用的編碼表

解碼:URLDecoder : HTML 格式解碼的實用工具類,解碼方法:

static String decode(String s, String enc) 參數(shù):s 解碼的字符串 enc 解碼使用的編碼表

*/

//編碼:URLEncoder:HTML 格式編碼的實用工具類。編碼方法:

// String encode = URLEncoder.encode(username, "ISO-8859-1");

// //解碼:URLDecoder : HTML 格式解碼的實用工具類,解碼方法:

// username = URLDecoder.decode(encode, "UTF-8");

方式二:

/*

解決post請求亂碼實現(xiàn):

方式二:

編碼:使用String類的方法進行編碼:byte[] getBytes(String charsetName) 參數(shù)表示指定的碼表

解碼:使用String類的構(gòu)造方法:String(byte[] bytes, String charsetName) 參數(shù):第一個參數(shù)是字節(jié)數(shù)組 第二個參數(shù)表示指定的碼表

*/

// 編碼:使用String類的方法進行編碼:byte[] getBytes(String charsetName) 參數(shù)表示指定的碼表

// byte[] bytes = username.getBytes("ISO-8859-1");

// // 解碼:使用String類的構(gòu)造方法:String(byte[] bytes, String charsetName) 參數(shù):第一個參數(shù)是字節(jié)數(shù)組 第二個參數(shù)表示指定的碼表

// username = new String(bytes, "UTF-8");

// username = new String(username.getBytes("ISO-8859-1"), "UTF-8");

方式三:解決post請求亂碼使用最多

/*

解決post請求亂碼實現(xiàn):

方式三:推薦使用

使用request對象調(diào)用方法: void setCharacterEncoding(String env) 參數(shù):env指定的編碼表

說明:

1.該方法是用來解決請求體數(shù)據(jù)的亂碼問題。get請求體沒有數(shù)據(jù),post請求體含有數(shù)據(jù)。可以認(rèn)為該方法就是解決post請求亂碼的

2.該方法必須放到獲取所有請求數(shù)據(jù)之前處理亂碼。

*/

//處理請求亂碼

request.setCharacterEncoding("utf-8");

2.4 Request請求轉(zhuǎn)發(fā)(-,*)

請求轉(zhuǎn)發(fā)(forward):一種在服務(wù)器內(nèi)部的資源跳轉(zhuǎn)方式。

(1)瀏覽器發(fā)送請求給服務(wù)器,服務(wù)器中對應(yīng)的資源A接收到請求

(2)資源A處理完請求后將請求發(fā)給資源B

(3)資源B處理完后將結(jié)果響應(yīng)給瀏覽器

(4)請求從資源A到資源B的過程就叫請求轉(zhuǎn)發(fā)

請求轉(zhuǎn)發(fā)的實現(xiàn)方式:

req.getRequestDispatcher("資源B路徑").forward(req,resp);

說明:

1)獲取這轉(zhuǎn)發(fā)器:RequestDispatcher dispatcher = req.getRequestDispatcher("資源B路徑");

2)轉(zhuǎn)發(fā):RequestDispatcher表示轉(zhuǎn)發(fā)器,該接口中有一個方法:forward(request,response)

具體如何來使用,我們先來看下需求:

針對上述需求,具體的實現(xiàn)步驟為:

1.創(chuàng)建一個RequestDemo5類,接收/req5的請求,在doGet方法中打印demo5

2.創(chuàng)建一個RequestDemo6類,接收/req6的請求,在doGet方法中打印demo6

3.在RequestDemo5的方法中使用

? req.getRequestDispatcher(“/req6”).forward(req,resp)進行請求轉(zhuǎn)發(fā)

4.啟動測試

(1)創(chuàng)建RequestDemo5類

/**

* 請求轉(zhuǎn)發(fā)

*/

@WebServlet("/req5")

public class RequestDemo5 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("demo5...");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(2)創(chuàng)建RequestDemo6類

/**

* 請求轉(zhuǎn)發(fā)

*/

@WebServlet("/req6")

public class RequestDemo6 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("demo6...");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3)在RequestDemo5的doGet方法中進行請求轉(zhuǎn)發(fā)

/**

* 請求轉(zhuǎn)發(fā)

*/

@WebServlet("/req5")

public class RequestDemo5 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("demo5...");

//請求轉(zhuǎn)發(fā)

request.getRequestDispatcher("/req6").forward(request,response);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(4)啟動測試

訪問http://localhost:8080/request-demo/req5,就可以在控制臺看到如下內(nèi)容:

說明請求已經(jīng)轉(zhuǎn)發(fā)到了/req6

請求轉(zhuǎn)發(fā)資源間共享數(shù)據(jù):使用Request域?qū)ο?/p>

此處主要解決的問題是把請求從/req5轉(zhuǎn)發(fā)到/req6的時候,如何傳遞數(shù)據(jù)給/req6。

需要使用request對象提供的三個方法:

存儲數(shù)據(jù)到request域[范圍,數(shù)據(jù)是存儲在request對象]中

void setAttribute(String name,Object o);

根據(jù)key獲取值

Object getAttribute(String name);

根據(jù)key刪除該鍵值對

void removeAttribute(String name);

接著上個需求來:

1.在RequestDemo5的doGet方法中轉(zhuǎn)發(fā)請求之前,將數(shù)據(jù)存入request域?qū)ο笾?/p>

2.在RequestDemo6的doGet方法從request域?qū)ο笾蝎@取數(shù)據(jù),并將數(shù)據(jù)打印到控制臺

3.啟動訪問測試

(1)修改RequestDemo5中的方法

@WebServlet("/req5")

public class RequestDemo5 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("demo5...");

//存儲數(shù)據(jù)

request.setAttribute("msg","hello");

//請求轉(zhuǎn)發(fā)

request.getRequestDispatcher("/req6").forward(request,response);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(2)修改RequestDemo6中的方法

/**

* 請求轉(zhuǎn)發(fā)

*/

@WebServlet("/req6")

public class RequestDemo6 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("demo6...");

//獲取數(shù)據(jù)

Object msg = request.getAttribute("msg");

System.out.println(msg);

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3)啟動測試

訪問http://localhost:8080/request-demo/req5,就可以在控制臺看到如下內(nèi)容:

此時就可以實現(xiàn)在轉(zhuǎn)發(fā)多個資源之間共享數(shù)據(jù)。

請求轉(zhuǎn)發(fā)的特點

瀏覽器地址欄路徑不發(fā)生變化 雖然后臺從/req5轉(zhuǎn)發(fā)到/req6,但是瀏覽器的地址一直是/req5,未發(fā)生變化 只能轉(zhuǎn)發(fā)到當(dāng)前服務(wù)器的內(nèi)部資源 不能從一個服務(wù)器通過轉(zhuǎn)發(fā)訪問另一臺服務(wù)器 一次請求,可以在轉(zhuǎn)發(fā)資源間使用request共享數(shù)據(jù) 雖然后臺從/req5轉(zhuǎn)發(fā)到/req6,但是這個只有一次請求 問題:request.getParameter()

request.getParameter(String name)和request.getAttribute(String name);區(qū)別

1.request.getParameter(String name):獲取來自于瀏覽器的數(shù)據(jù)

request.getParameter("username"); 獲取的是鎖哥

2.request.getAttribute(String name)獲取的是服務(wù)器中的代碼:request.setAttibute(String name,Object obj);的數(shù)據(jù)

request.setAttribute("msg","黑馬程序員");

String msg = (String) request.getAttribute("msg");

2.5 request的生命周期

1.何時創(chuàng)建?

瀏覽器第一次訪問tomcat服務(wù)器的時候

2.誰創(chuàng)建?

tomcat創(chuàng)建

3.創(chuàng)建對象做什么?

瀏覽器第一次訪問tomcat服務(wù)器的時候,tomcat創(chuàng)建request對象和response對象,傳遞給servlet中的service方法,然后我們可以在servlet中使用request對象調(diào)用方法獲取請求數(shù)據(jù)(請求行 頭 體),然后處理業(yè)務(wù)邏輯,處理完畢,然后tomcat將響應(yīng)數(shù)據(jù)給瀏覽器,瀏覽器接收到響應(yīng)之后,tomcat立刻銷毀request和response對象。

3.HTTP響應(yīng)詳解(理解)

1.使用抓包查看響應(yīng)報文協(xié)議內(nèi)容

學(xué)習(xí)目標(biāo)

能夠使用抓包查看響應(yīng)報文協(xié)議內(nèi)容

內(nèi)容講解

注意:

http響應(yīng)報文協(xié)議包括:

1.響應(yīng)行

2.響應(yīng)頭

3.響應(yīng)體

響應(yīng)數(shù)據(jù):是服務(wù)器響應(yīng)給瀏覽器

【1】步驟

1.創(chuàng)建html頁面

2.創(chuàng)建servlet

【2】實現(xiàn)

1.創(chuàng)建html頁面

Insert title here

get請求

用戶名:

密碼:

post請求

用戶名:

密碼:

2.創(chuàng)建servlet

package com.example.sh.a_http_01;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/getServlet")

public class GetServlet extends HttpServlet {

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//響應(yīng)給瀏覽器數(shù)據(jù)

response.getWriter().print("get....");

}

}

package com.example.sh.a_http_01;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/postServlet")

public class PostServlet extends HttpServlet {

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

doGet(request, response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//響應(yīng)給瀏覽器數(shù)據(jù)

response.getWriter().print("post....");

}

}

【3】抓包結(jié)果

內(nèi)容小結(jié)

? 1.由于瀏覽器的原因,瀏覽器會把請求行和響應(yīng)行信息放在了一起;

? 2.get和post請求的響應(yīng)沒有區(qū)別;

2.HTTP響應(yīng)報文協(xié)議介紹

學(xué)習(xí)目標(biāo)

理解響應(yīng)報文協(xié)議的組成部分

內(nèi)容講解

【1】響應(yīng)行

響應(yīng)行格式:協(xié)議/版本 狀態(tài)碼

如:HTTP/1.1 200 ;

狀態(tài)碼狀態(tài)碼描述說明200OK請求已成功,請求所希望的響應(yīng)頭或數(shù)據(jù)體將隨此響應(yīng)返回。出現(xiàn)此狀態(tài)碼是表示正常狀態(tài)。302Move temporarily重定向,請求的資源臨時從不同的 地址響應(yīng)請求。304Not Modified從瀏覽器緩存中讀取數(shù)據(jù),不從服務(wù)器重新獲取數(shù)據(jù)。例如,用戶第一次從瀏覽器訪問服務(wù)器端圖片資源,以后在訪問該圖片資源的時候就不會再從服務(wù)器上加載而直接到瀏覽器緩存中加載,這樣效率更高。404Not Found請求資源不存在。通常是用戶路徑編寫錯誤,也可能是服務(wù)器資源已刪除。403Forbidden服務(wù)器已經(jīng)理解請求,但是拒絕執(zhí)行它405Method Not Allowed請求行中指定的請求方法不能被用于請求相應(yīng)的資源500Internal Server Error服務(wù)器內(nèi)部錯誤。通常程序拋異常

【2】響應(yīng)頭

響應(yīng)頭也是用的鍵值對key:value,服務(wù)器基于響應(yīng)頭通知瀏覽器的行為。

常見的響應(yīng)頭 :

響應(yīng)頭Key響應(yīng)頭valuelocation指定響應(yīng)的路徑,需要與狀態(tài)碼302配合使用,完成重定向content-Type響應(yīng)正文的類型(MIME類型,屬于服務(wù)器里面的一種類型,例如文件在window系統(tǒng)有自己的類型,.txt .doc .jpg。文件在服務(wù)器中也有自己的類型),同時還可以解決亂碼問題。例如:text/html;charset=UTF-8content-disposition通過瀏覽器以附件形式解析正文,例如:attachment;filename=xx.ziprefresh頁面刷新,例如:3;url=www.itcast.cn //三秒刷新頁面到www.itcast.cn

常見的MIME類型:就是文件在tomcat服務(wù)器中的文件類型:

windows tomcat(MIME類型)

超文本標(biāo)記語言文本 .html text/html ***

xml文檔 .xml text/xml

XHTML文檔 .xhtml application/xhtml+xml

普通文本 .txt text/plain ***

PDF文檔 .pdf application/pdf

Microsoft Word文件 .word application/msword

PNG圖像 .png image/png **

GIF圖形 .gif image/gif

JPEG圖形 .jpeg,.jpg image/jpeg **

......

【3】響應(yīng)體

? 響應(yīng)體,就是服務(wù)器發(fā)送給瀏覽器的數(shù)據(jù)。當(dāng)前瀏覽器向服務(wù)器請求的資源是hello.html,所以服務(wù)器給瀏覽器響應(yīng)的數(shù)據(jù)是一個html頁面。

請求資源路徑:

響應(yīng)結(jié)果:

如果請求是servlet,那么瀏覽器的響應(yīng)體接收到的是servlet響應(yīng)的數(shù)據(jù):

內(nèi)容小結(jié)

1.響應(yīng)行:

? 協(xié)議版本號 狀態(tài)碼 200(一切正常) 404(找不到資源路徑) 500(服務(wù)器報異常) 302(和location一起使用,實現(xiàn)重定向) 304(從瀏覽器緩存中讀取數(shù)據(jù)) 405(服務(wù)器的servlet沒有重寫doGet和doPost方法)

2.響應(yīng)頭:

? location 指定響應(yīng)的路徑

? content-type:告訴瀏覽器文件格式,告訴瀏覽器不要解析html文件(text/plain),解決中文亂碼問題

? refresh 定時刷新

? content-disposition 以附件形式展示圖片等資源

3.響應(yīng)體:

? 服務(wù)器處理的結(jié)果響應(yīng)到瀏覽器中

4.Response對象

1 Response對象介紹

前面講解完Request對象,接下來我們回到剛開始的那張圖:

Request:使用request對象來獲取請求數(shù)據(jù)Response:使用response對象來設(shè)置響應(yīng)數(shù)據(jù)

Reponse的繼承體系和Request的繼承體系也非常相似:

HttpServletResponse response = new ResponseFacade();多態(tài)

介紹完Response的相關(guān)體系結(jié)構(gòu)后,接下來對于Response我們需要學(xué)習(xí)如下內(nèi)容:

Response設(shè)置響應(yīng)數(shù)據(jù)的功能介紹Response完成重定向Response響應(yīng)字符數(shù)據(jù)Response響應(yīng)字節(jié)數(shù)據(jù)

2 Response設(shè)置響應(yīng)數(shù)據(jù)功能介紹

HTTP響應(yīng)數(shù)據(jù)總共分為三部分內(nèi)容,分別是響應(yīng)行、響應(yīng)頭、響應(yīng)體,對于這三部分內(nèi)容的數(shù)據(jù),respone對象都提供了哪些方法來進行設(shè)置?

響應(yīng)行

對于響應(yīng)行,比較常用的就是設(shè)置響應(yīng)狀態(tài)碼:

void setStatus(int sc);

響應(yīng)頭

設(shè)置響應(yīng)頭鍵值對:

void setHeader(String name,String value);

響應(yīng)頭:name的值

location 指定響應(yīng)的路徑

content-type:告訴瀏覽器文件格式,告訴瀏覽器不要解析html文件(text/plain),解決中文亂碼問題 ************

refresh 定時刷新

content-disposition 以附件形式展示圖片等資源

響應(yīng)體

對于響應(yīng)體,是通過字符、字節(jié)輸出流的方式往瀏覽器寫,

獲取字符輸出流:

PrintWriter getWriter();

獲取字節(jié)輸出流

ServletOutputStream getOutputStream();

介紹完這些方法后,后面我們會通過案例把這些方法都用一用,首先先來完成下重定向的功能開發(fā)。

3 Respones請求重定向

Response重定向(redirect):一種資源跳轉(zhuǎn)方式(服務(wù)器外部的)。

(1)瀏覽器發(fā)送請求給服務(wù)器,服務(wù)器中對應(yīng)的資源A接收到請求

(2)資源A現(xiàn)在無法處理該請求,就會給瀏覽器響應(yīng)一個302的狀態(tài)碼+location的一個訪問資源B的路徑

(3)瀏覽器接收到響應(yīng)狀態(tài)碼為302就會重新發(fā)送請求到location對應(yīng)的訪問地址去訪問資源B

(4)資源B接收到請求后進行處理并最終給瀏覽器響應(yīng)結(jié)果,這整個過程就叫重定向

重定向的實現(xiàn)方式:

resp.setStatus(302);設(shè)置響應(yīng)狀態(tài)碼是302

resp.setHeader("location","資源B的訪問路徑");

具體如何來使用,我們先來看下需求:

針對上述需求,具體的實現(xiàn)步驟為:

1.創(chuàng)建一個ResponseDemo1類,接收/resp1的請求,在doGet方法中打印resp1....

2.創(chuàng)建一個ResponseDemo2類,接收/resp2的請求,在doGet方法中打印resp2....

3.在ResponseDemo1的方法中使用

? response.setStatus(302);

? response.setHeader(“Location”,“/request-demo/resp2”) 來給前端響應(yīng)結(jié)果數(shù)據(jù)

4.啟動測試

(1)創(chuàng)建ResponseDemo1類

@WebServlet("/resp1")

public class ResponseDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("resp1....");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(2)創(chuàng)建ResponseDemo2類

@WebServlet("/resp2")

public class ResponseDemo2 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("resp2....");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(3)在ResponseDemo1的doGet方法中給前端響應(yīng)數(shù)據(jù)

@WebServlet("/resp1")

public class ResponseDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("resp1....");

//重定向

//1.設(shè)置響應(yīng)狀態(tài)碼 302

response.setStatus(302);

//2. 設(shè)置響應(yīng)頭 Location

response.setHeader("Location","/request-demo/resp2");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

(4)啟動測試

訪問http://localhost:8080/request-demo/resp1,就可以在控制臺看到如下內(nèi)容:

說明/resp1和/resp2都被訪問到了。到這重定向就已經(jīng)完成了。

雖然功能已經(jīng)實現(xiàn),但是從設(shè)置重定向的兩行代碼來看,會發(fā)現(xiàn)除了重定向的地址不一樣,其他的內(nèi)容都是一模一樣,所以resposne對象給我們提供了簡化的編寫方式為:

resposne.sendRedirect("/request-demo/resp2")

所以第3步中的代碼就可以簡化為:

@WebServlet("/resp1")

public class ResponseDemo1 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

System.out.println("resp1....");

//重定向

resposne.sendRedirect("/request-demo/resp2");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

重定向的特點

瀏覽器地址欄路徑發(fā)送變化 當(dāng)進行重定向訪問的時候,由于是由瀏覽器發(fā)送的兩次請求,所以地址會發(fā)生變化 可以重定向到任何位置的資源(服務(wù)內(nèi)容、外部均可) 因為第一次響應(yīng)結(jié)果中包含了瀏覽器下次要跳轉(zhuǎn)的路徑,所以這個路徑是可以任意位置資源。 兩次請求,不能在多個資源使用request共享數(shù)據(jù) 因為瀏覽器發(fā)送了兩次請求,是兩個不同的request對象,就無法通過request對象進行共享數(shù)據(jù)

介紹完請求重定向和請求轉(zhuǎn)發(fā)以后,接下來需要把這兩個放在一塊對比下:

以后到底用哪個,還是需要根據(jù)具體的業(yè)務(wù)來決定。

# 如果需要在資源之間傳遞共享request數(shù)據(jù),使用請求轉(zhuǎn)發(fā), 否則就用重定向

4 路徑問題

問題1:轉(zhuǎn)發(fā)的時候路徑上沒有加/request-demo而重定向加了,那么到底什么時候需要加,什么時候不需要加呢?

其實判斷的依據(jù)很簡單,只需要記住下面的規(guī)則即可:

瀏覽器使用:需要加虛擬目錄(項目訪問路徑)服務(wù)端使用:不需要加虛擬目錄

對于轉(zhuǎn)發(fā)來說,因為是在服務(wù)端進行的,所以不需要加虛擬目錄

對于重定向來說,路徑最終是由瀏覽器來發(fā)送請求,就需要添加虛擬目錄。

掌握了這個規(guī)則,接下來就通過一些練習(xí)來強化下知識的學(xué)習(xí):

req.getRequestDispatcher(“路徑”)resp.sendRedirect(“路徑”)

答案:

1.超鏈接,從瀏覽器發(fā)送,需要加

2.表單,從瀏覽器發(fā)送,需要加

3.重定向,是由瀏覽器進行跳轉(zhuǎn),需要加。

4.轉(zhuǎn)發(fā),是從服務(wù)器內(nèi)部跳轉(zhuǎn),不需要加

5 Response響應(yīng)字符數(shù)據(jù)

要想將字符數(shù)據(jù)寫回到瀏覽器,我們需要兩個步驟:

通過Response對象獲取字符輸出流: PrintWriter writer = resp.getWriter(); 由于獲取打印字符流是根據(jù)response對象獲取的,所以向瀏覽器打印輸出 通過字符輸出流寫數(shù)據(jù): writer.write(“aaa”);

接下來,我們實現(xiàn)通過些案例把響應(yīng)字符數(shù)據(jù)給實際應(yīng)用下:

返回一個簡單的字符串a(chǎn)aa

/**

* 響應(yīng)字符數(shù)據(jù):設(shè)置字符數(shù)據(jù)的響應(yīng)體

*/

@WebServlet("/resp3")

public class ResponseDemo3 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

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

//1. 獲取字符輸出流

PrintWriter writer = response.getWriter();

writer.write("aaa");

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

返回一串html字符串,并且能被瀏覽器解析

PrintWriter writer = response.getWriter();

//content-type,告訴瀏覽器返回的數(shù)據(jù)類型是HTML類型數(shù)據(jù),這樣瀏覽器才會解析HTML標(biāo)簽

response.setHeader("content-type","text/html");

writer.write("

aaa

");

==注意:==一次請求響應(yīng)結(jié)束后,response對象就會被銷毀掉,所以不要手動關(guān)閉流。

返回一個中文的字符串你好,需要注意設(shè)置響應(yīng)數(shù)據(jù)的編碼為utf-8

//設(shè)置響應(yīng)的數(shù)據(jù)格式及數(shù)據(jù)的編碼

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

writer.write("你好");

6 Response響應(yīng)字節(jié)數(shù)據(jù)

要想將字節(jié)數(shù)據(jù)寫回到瀏覽器,我們需要兩個步驟:

通過Response對象獲取字節(jié)輸出流:ServletOutputStream outputStream = resp.getOutputStream(); 通過字節(jié)輸出流寫數(shù)據(jù): outputStream.write(字節(jié)數(shù)據(jù));

接下來,我們實現(xiàn)通過些案例把響應(yīng)字節(jié)數(shù)據(jù)給實際應(yīng)用下:

返回一個圖片文件到瀏覽器

/**

* 響應(yīng)字節(jié)數(shù)據(jù):設(shè)置字節(jié)數(shù)據(jù)的響應(yīng)體

*/

@WebServlet("/resp4")

public class ResponseDemo4 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1. 讀取文件

FileInputStream fis = new FileInputStream("D:\\abc\\柳巖.jpg");

//2. 獲取response字節(jié)輸出流

ServletOutputStream os = response.getOutputStream();

//3. 完成流的copy

byte[] buff = new byte[1024];

int len = 0;

while ((len = fis.read(buff))!= -1){

os.write(buff,0,len);

}

fis.close();

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

上述代碼中,對于流的copy的代碼還是比較復(fù)雜的,所以我們可以使用別人提供好的方法來簡化代碼的開發(fā),具體的步驟是:

(1)pom.xml添加依賴

commons-io

commons-io

2.6

(2)調(diào)用工具類方法

//fis:輸入流

//os:輸出流

IOUtils.copy(fis,os);

優(yōu)化后的代碼:

/**

* 響應(yīng)字節(jié)數(shù)據(jù):設(shè)置字節(jié)數(shù)據(jù)的響應(yīng)體

*/

@WebServlet("/resp4")

public class ResponseDemo4 extends HttpServlet {

@Override

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

//1. 讀取文件

FileInputStream fis = new FileInputStream("d://a.jpg");

//2. 獲取response字節(jié)輸出流

ServletOutputStream os = response.getOutputStream();

//3. 完成流的copy

IOUtils.copy(fis,os);

fis.close();

}

@Override

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doGet(request, response);

}

}

回顧

# http協(xié)議

1. 超文本傳輸協(xié)議

目前web領(lǐng)域最常用的協(xié)議

2. 特點

1). 基于tcp, 面向連接, 安全

2). 基于請求-響應(yīng)模型: 一次請求對應(yīng)一次響應(yīng)

3). 無狀態(tài),每次請求都相互獨立,無法共享數(shù)據(jù)

I. 優(yōu)點 : 速度快

II. 缺點 : 多次請求無法共享數(shù)據(jù),需要其他技術(shù)彌補(會話技術(shù))

4). http協(xié)議默認(rèn)端口80(可以省略)

3. 內(nèi)容

1). 請求數(shù)據(jù)(報文)

I. 請求行

請求方式, 請求地址, 協(xié)議

II. 請求頭

key : value

III. 請求體

用于post請求存放請求參數(shù)

get請求沒有請求體,get請求參數(shù)在請求行中(在請求地址里)

2). 響應(yīng)數(shù)據(jù)

I. 響應(yīng)行

協(xié)議, 狀態(tài)碼(status code)

200 : 請求成功

404 : not found (請求地址錯誤)

500 : 服務(wù)器錯誤

302 : 重定向

II. 響應(yīng)頭

key : value

III. 響應(yīng)體

響應(yīng)數(shù)據(jù)的正文

tomcat

web服務(wù)器,apache出品的開源免費的軟件 能夠解析http協(xié)議 默認(rèn)占用8080端口基本使用 1). 啟動 bin/startup.bat 2). 配置 conf/server.xml(修改服務(wù)器設(shè)置,包括端口) conf/web.xml(修改部署項目的設(shè)置) 3). 部署 webapps目錄下放war包 4). 查看日志 logs目錄idea中集成tomcat

# Servlet

1. 服務(wù)器小程序, 需要運行web服務(wù)器上

在java中的體現(xiàn),是javaee的一種規(guī)范,類型為接口

2. 執(zhí)行原理

1). servlet對象是web服務(wù)器創(chuàng)建的

2). servlet的方法是web服務(wù)器調(diào)用的

3. 生命周期方法

1). init

2). service

3). destroy

4). 啟動加載 : loadOnStartup >= 0

4. urlPattern

1). 精準(zhǔn)匹配

2). 目錄匹配

3). 擴展名匹配

4). 缺省匹配

5. servlet的配置方式

1). 注解配置 WebServlet

2). xml配置 (web.xml)

總結(jié)

# Request

1. 是什么: 表示請求數(shù)據(jù), 瀏覽器發(fā)送給服務(wù)器的是數(shù)據(jù)

2. 為什么:

1). 見名知意

2). request對象是由tomcat創(chuàng)建的,tomcat會解析瀏覽器發(fā)送過來的數(shù)據(jù),并封裝到request對象中

3. 怎么辦:

1). 我們(servlet開發(fā)者)可以通過request對象獲取請求數(shù)據(jù)

I. 請求行

a. 內(nèi)容 : 請求方式, 請求地址, 請求協(xié)議

b. 請求方式: get/post

c. get的請求參數(shù)在請求地址中

d. API :

II. 請求頭

a. 格式 key : value

b. 請求頭 user-agent (用戶代理: 用戶操作系統(tǒng)和瀏覽器)

c. API

String value = request.getHeader("user-agent");

III. 請求體

a. post請求參數(shù)在這里,get沒有請求體

IV. 通用的獲取請求參數(shù)的API

V. 請求參數(shù)中文亂碼

a. 現(xiàn)象

tomcat7

tomcat8

b. 原因

c. 解決方案

2). 我們可以通過request對象實現(xiàn)請求轉(zhuǎn)發(fā)

I. 是服務(wù)器內(nèi)部的一種資源跳轉(zhuǎn)方式(資源包括html,Servlet)

II. 特點

a. 就只有一次請求,可以通過request域?qū)ο蠊蚕頂?shù)據(jù)

b. 地址欄不會變化

c. 只能跳轉(zhuǎn)服務(wù)器內(nèi)部的其他資源

III. API

# Response

1. 是什么 : 表示響應(yīng)數(shù)據(jù), 服務(wù)器發(fā)送給瀏覽器的數(shù)據(jù)

2. 為什么 :

response對象是tomcat創(chuàng)建的

3. 怎么辦

1). 我們可以通過response設(shè)置響應(yīng)數(shù)據(jù)

I. 響應(yīng)行

a. 內(nèi)容: 協(xié)議,狀態(tài)碼

b. 常見狀態(tài)碼(status code)

200

302

404

500

c. 通常情況下,tomcat會設(shè)置狀態(tài)碼,只有重定向才需要手動設(shè)置

II. 響應(yīng)頭

a. 格式 key:value

b. location : 重定向時指定資源位置的

c. content-type : 可以用來防止響應(yīng)體中文字符亂碼的

III. 響應(yīng)體

a. 字符輸出流

b. 字節(jié)輸出流

2). 重定向功能

I. 是一種資源跳轉(zhuǎn)方式

II. 特點:

a. 起碼兩次請求,不可以通過request域?qū)ο蠊蚕頂?shù)據(jù)

b. 地址欄會發(fā)生變化

c. 可以實現(xiàn)任意位置資源跳轉(zhuǎn),無論服務(wù)器內(nèi)部還是外部

3). 響應(yīng)字符/字節(jié)數(shù)據(jù)

0.Servlet : 屬于一個接口,動態(tài)資源,如果瀏覽器想訪問服務(wù)器中的動態(tài)資源,那么需要自定義類直接或者間接實現(xiàn)Servlet接口

1)自定義類實現(xiàn)Servlet接口===自定義類中要實現(xiàn)Servlet接口中的全部的抽象方法

2)自定義類繼承GenericServlet====只需要重寫ervice方法

3)自定義類繼承HttpServlet===》需要重寫doGet doPost方法 ******

1.request:處理瀏覽器向服務(wù)器發(fā)送請求的數(shù)據(jù)的(請求行 請求頭 請求體)

2.request繼承體系:

ServletRequest(父接口)==== HttpServletRequest(子接口) === RequestFacade(實現(xiàn)類,tomcat定義)

3.獲取請求參數(shù):

1)Map getParameterMap();頁面中所有的請求參數(shù) name屬性值或者key作為map集合的鍵,提交的數(shù)據(jù)作為map集合的值 username:張三

2)String[] getParameterValues(String name) 獲取指定的name的值,是一個數(shù)組

3)String getParameter(String name)獲取指定的name的值,一個值

4.處理請求亂碼:

1)

URLEncoder.encode(字符串,編碼表); 編碼

URLDecoder.decode(字符串,編碼表); 解碼

2)String類

Byte[] 字符串.getBytes("編碼表");編碼

String s = new String(字節(jié)數(shù)組,編碼表);解碼

3)

只是解決請求體亂碼的,即解決post

request.setCharacterEncoding(編碼表);

5.請求轉(zhuǎn)發(fā):屬于服務(wù)器內(nèi)部跳轉(zhuǎn)。地址不發(fā)生改變,只有一次請求一次響應(yīng),可以共享request數(shù)據(jù)

request.getRequestDispatcher("/loginServlet").forward(request,response); 只要通過瀏覽器訪問必須加虛擬路徑day03

補充:絕對路徑:

1)http://localhost:8080/day03/loginServlet

2)/day03/loginServlet 省略三要素,必須加/

6.response:處理服務(wù)器響應(yīng)數(shù)據(jù)(響應(yīng)行 響應(yīng)頭 響應(yīng)體)給瀏覽器

7.繼承體系:

ServletResponse(父接口)==== HttpServletResponse(子接口) === ResponseFacade(實現(xiàn)類,tomcat定義)

8.響應(yīng)行:狀態(tài)碼 200 404 500 302 304(從瀏覽器緩存中獲取)

9.設(shè)置響應(yīng)頭:response.setHeader("content-type","text/html;charset=utf-8") MIME:文件在tomcat服務(wù)器中的類型

response.setContentType("text/html;charset=utf-8")//告知瀏覽器文件的MIME類型并解決響應(yīng)亂碼問題

10.響應(yīng)體:

1)響應(yīng)字符數(shù)據(jù):response.getWriter().print();

2) 響應(yīng)字節(jié)數(shù)據(jù):response.getOutputStream()響應(yīng)字節(jié)數(shù)據(jù)

11.重定向:實現(xiàn)服務(wù)器外部跳轉(zhuǎn),多次請求和響應(yīng),不能共享request數(shù)據(jù),地址發(fā)生改變

1)

response.setStatus(302);

response.setHeader("location","/day03/loginServlet");必須加虛擬路徑,因為屬于服務(wù)器外部,經(jīng)過瀏覽器再次向服務(wù)器發(fā)送請求

2)

response.sendRedirect("/day03/loginServlet");

柚子快報激活碼778899分享:Servlet中的請求與響應(yīng)

http://yzkb.51969.com/

好文閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/18995593.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄