一讶迁、簡介
(1) web服務(wù)器收到客戶端的http請求吭从,會針對每一次請求绣版,分別創(chuàng)建一個(gè)用于代表請求的request對象和代表響應(yīng)的request對象蚂四。
(2)request和response對象既然代表請求和響應(yīng),那我們要獲取客戶端(瀏覽器)提交過來的數(shù)據(jù)跨琳,只需要找request對象就行了自点。要客戶端輸出數(shù)據(jù),只需要找response對象就行了脉让。
注意:request中封裝的是瀏覽器的信息和請求參數(shù)桂敛,即瀏覽器的請求;response中封裝的是服務(wù)器向?yàn)g覽器發(fā)送的數(shù)據(jù)溅潜、響應(yīng)頭和編碼格式等术唬,即服務(wù)器的響應(yīng)。
二滚澜、HttpServletResponse
HttpServletResponse對象服務(wù)器的響應(yīng)粗仓。這個(gè)對象中封裝了向客戶端發(fā)送數(shù)據(jù)、發(fā)送響應(yīng)頭和發(fā)送狀態(tài)碼的方法设捐。
2.1 response常見應(yīng)用(工程ResAndReq)
2.1.1向?yàn)g覽器輸出中文數(shù)據(jù)
package cn.itcast.response;
//向?yàn)g覽器輸出中文
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
test2(response);
}
public void test1(HttpServletResponse response) throws IOException{
String data = "中國";
//設(shè)置碼表頭借浊,告訴瀏覽器打開文本時(shí)應(yīng)該使用的碼表
response.setHeader("content-type", "text/html;charset=UTF-8");
//直接從response對象中獲得輸出流
OutputStream out = response.getOutputStream();
byte[] b = data.getBytes("UTF-8");
out.write(b);//注意使用字節(jié)流
}
public void test2(HttpServletResponse response) throws IOException{
String data = "中國";
response.setHeader("content-type", "text/html;charset=UTF-8");
//設(shè)置response的碼表
response.setCharacterEncoding("UTF-8");
//這行代碼相當(dāng)于上面兩行代碼的功能
//response.setContentType("text/html;charset=UTF-8");
//因?yàn)閞espon使用的碼表是iso-8859-1,于是會使用此碼表編碼信息挡育,這樣是找不到漢字的巴碗,
//所以我們需要在上面設(shè)置response的碼表
PrintWriter out = response.getWriter();
out.write(data);
//注意:OutputSream和PrintWriter的區(qū)別,后者一般是輸出字符串內(nèi)容個(gè)即寒,多用于輸出網(wǎng)頁文本
//而前者是字節(jié)流橡淆,可以處理任何數(shù)據(jù),但是兩者不能同時(shí)使用母赵。
}
//顯示數(shù)字
public void test3(HttpServletResponse response) throws IOException{
//但是我們發(fā)現(xiàn)瀏覽器中顯示的不是1逸爵,這是因?yàn)闉g覽器是一種文本顯示,它會先查看1對應(yīng)
//碼表中是哪個(gè)字符凹嘲,然后顯示师倔,所以這里我們需要先將數(shù)字轉(zhuǎn)換成字符串
response.getOutputStream().write(1);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.1.2文件下載和中文名字文件的下載
package cn.itcast.response;
//文件下載,瀏覽器中會彈出下載窗口
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
test2(response);
}
private void test1(HttpServletResponse response) throws IOException{
String path = this.getServletContext().getRealPath("/download/1.jpg");
String filename = path.substring(path.lastIndexOf("\\") + 1);
//其中content-disposition是http頭周蹭,告訴瀏覽器使用下載方式打開
response.setHeader("content-disposition", "attachment;filename="+filename);
FileInputStream in = new FileInputStream(path);
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer)) > 0){
out.write(buffer, 0, len);
}
in.close();
//注意:瀏覽器關(guān)閉后會自動關(guān)閉和response關(guān)聯(lián)的流趋艘,我們不需要專門關(guān)閉
}
//當(dāng)圖片的名字含有中文
private void test2(HttpServletResponse response) throws IOException{
String path = this.getServletContext().getRealPath("/download/圖片.jpg");
String filename = path.substring(path.lastIndexOf("\\") + 1);
//其中方法URLEncoder.encode會將文件名轉(zhuǎn)換成ASCII碼
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
FileInputStream in = new FileInputStream(path);
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while((len = in.read(buffer)) > 0){
out.write(buffer, 0, len);
}
in.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
注意:在開發(fā)中盡量使用字節(jié)流,因?yàn)樽止?jié)流可以處理任何數(shù)據(jù)凶朗,而字符流只能用來處理文本瓷胧。
2.1.3輸出隨機(jī)圖片(如驗(yàn)證碼)
package cn.itcast.response;
//輸出一張帶有隨機(jī)數(shù)的圖片
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//6.設(shè)置頭,控制瀏覽器不要緩存圖片棚愤,為了兼容性搓萧,三種類型的頭都需要聲明
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
//5.通知瀏覽器以圖片方式打開
response.setHeader("content-type", "image/jpeg");
//1.在內(nèi)存中創(chuàng)建一副圖片杂数,80是寬,20是高瘸洛,一般都是使用TYPE_INT_BGR
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_BGR);
//2.得到圖片
Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setColor(Color.WHITE);//設(shè)置圖片顏色
graphics.fillRect(0, 0, 80, 20);//重繪圖片的范圍
//3.向圖片上寫數(shù)據(jù)
graphics.setColor(Color.RED);//設(shè)置圖片上的顏色
graphics.setFont(new Font(null, Font.BOLD, 20));//設(shè)置字體揍移,null表示使用默認(rèn)字體,加粗
//graphics.drawString("123", 0, 20);這是向圖片上寫一個(gè)固定的值123
graphics.drawString(makeNum(), 0, 20);//這里我們向圖片上寫入一個(gè)隨機(jī)值
//4.將圖片寫給瀏覽器
ImageIO.write(image, "jpg", response.getOutputStream());
}
private String makeNum(){
Random r = new Random();
String num = r.nextInt(9999) + "";//產(chǎn)生一個(gè)0-9999的數(shù)字反肋,但又可能不足四位那伐,我們需要補(bǔ)零
StringBuffer sb = new StringBuffer();
for(int i = 0; i < 4 - num.length(); i++){
sb.append("0");
}
num = sb.toString() + num;
return num;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.1.4更多頭信息
package cn.itcast.response;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("refresh", "5");//每五秒刷新一次
response.setHeader("content-type", "text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
response.getWriter().write("我是Tom");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.2通過response實(shí)現(xiàn)請求重定向
package cn.itcast.response;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//方式一、通過設(shè)置頭的方式石蔗,但是這種方式我們不推薦喧锦,因?yàn)闀蚍?wù)器發(fā)兩次請求
//會降低服務(wù)器的性能,同時(shí)注意:瀏覽器中的地址發(fā)生了變化
/*response.setHeader("location", "/ResAndReq/register.html");
response.setStatus(302);*/
//方式二:推薦使用此方式
response.sendRedirect("/ResAndReq/register.html");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
2.3 response細(xì)節(jié)
(1)getOutputStream和getWriter方法分別用于得到輸出二進(jìn)制數(shù)據(jù)抓督、輸出文本數(shù)據(jù)的ServletOutputStream、PrintWriter對象束亏。
(2)getOutputStream和getWriter這兩個(gè)方法互相排斥铃在,調(diào)用其中的任何一個(gè)方法后,就不能再調(diào)用另一個(gè)方法碍遍。
(3)servlet程序向ServletOutputStream和PrintWriter對象中寫入的數(shù)據(jù)將被servlet引擎從response里面獲取定铜,servlet引擎將這些數(shù)據(jù)當(dāng)作響應(yīng)消息的正文乓土,然后再與響應(yīng)狀態(tài)行和各響應(yīng)頭組合后輸出到客戶端哄芜。
(4)servlet的service方法結(jié)束后,servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經(jīng)調(diào)用過close方法稠腊,如果沒有东跪,servlet引擎將調(diào)用close方法關(guān)閉該輸出對象畸陡。
2.3.1 各類地址的寫法
web工程中url地址的寫法,不要用絕對地址,只要是寫地址請一定使用斜杠(/)開頭,這個(gè)斜杠如果是給服務(wù)器用的就代表web工程(WebRoot),如果是給瀏覽器用的就代表webapps虽填。如果要讀取硬盤下的東西那使用"\",比如c:\aaa\bbb丁恭,如果處理的是一個(gè)url資源的話那就使用"/"這種斜杠。在web開發(fā)中需要用到地址的情況有servletContext斋日、forward牲览、sendRedirect、html恶守。
package cn.itcast.response;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//ServletContext(WebRoot下download/1.jpg)
this.getServletContext().getRealPath("/download/1.jpg");
//forward(WebRoot/register.html)
this.getServletContext().getRequestDispatcher("/register.html");
//sendRedirect(WebRoot/register.html)
response.sendRedirect("/ResAndReq/register.html");
//html中
//<a href="/ResAndReq/servlet/ResponseDemo5">按鈕</a>
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
三第献、HttpServletRequest
HttpServletRequest對象代表客戶端的請求,當(dāng)客戶端通過HTTP協(xié)議訪問服務(wù)器時(shí)兔港,HTTP請求頭的所有信息都封裝在這個(gè)對象中庸毫,開發(fā)人員通過這個(gè)對象的方法,可以獲得客戶這些信息押框。
3.1常用方法
3.1.1獲得瀏覽器的信息
getRequestURL()方法返回客戶端發(fā)出請求時(shí)完整的URL
getRequestURI()方法返回請求行中的資源名部分
getQueryString()方法返回請求行中的參數(shù)部分
getRemoteAddr()方法返回請求的客戶機(jī)的完整IP地址
getRemoteHost()方法返回發(fā)出請求的客戶機(jī)的完整主機(jī)名
getRemotePort()方法返回客戶機(jī)所使用的網(wǎng)絡(luò)端口號
getLocalAddr()方法返回Web服務(wù)器的IP地址
getLocalName()方法返回Web服務(wù)器的主機(jī)名
getMethod()得到客戶機(jī)的請求方式
例1:獲取瀏覽器環(huán)境信息
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//結(jié)果:http://localhost:8080/ResAndReq/servlet/RequestDemo1
System.out.println(request.getRequestURL());
//結(jié)果:/ResAndReq/servlet/RequestDemo1
System.out.println(request.getRequestURI());
//結(jié)果:null岔绸,這里我們沒帶參數(shù),如果使用
//http://localhost:8080/ResAndReq/servlet/RequestDemo1?name=yj訪問
//就會返回name=yj
System.out.println(request.getQueryString());
//結(jié)果:0:0:0:0:0:0:0:1這是來訪者的地址(IPV6)
System.out.println(request.getRemoteAddr());
//結(jié)果:0:0:0:0:0:0:0:1,注冊了才能返回主機(jī)名盒揉,否則返回此地址
System.out.println(request.getRemoteHost());
//結(jié)果:19404返回瀏覽器端口號
System.out.println(request.getRemotePort());
//結(jié)果:0:0:0:0:0:0:0:1返回web服務(wù)器的IP地址
System.out.println(request.getLocalAddr());
//結(jié)果:0:0:0:0:0:0:0:1服務(wù)器的主機(jī)名晋被,沒有注冊所有返回此地址
System.out.println(request.getLocalName());
//結(jié)果:GET這里我們使用的是GET方式
System.out.println(request.getMethod());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.1.2獲得瀏覽器的請求頭
getHeader(String name)方法
getHeaders(String name)方法
getHeaderNames方法
例1.獲取請求頭
package cn.itcast.request;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取請求頭,但是這個(gè)頭可能出現(xiàn)多次刚盈,此時(shí)我們可以使用getHeaders方法
String head = request.getHeader("Accept-Encoding");
System.out.println(head);
if(head.contains("gzip")){
//看是否包含gzip頭羡洛,若存在,再向其輸出壓縮數(shù)據(jù)
}else{
//不存在則輸出沒有壓縮的數(shù)據(jù)
}
//當(dāng)一個(gè)頭出現(xiàn)多次
Enumeration e = request.getHeaders("Accept-Encoding");
while(e.hasMoreElements()){
String value = (String) e.nextElement();
System.out.println(value);
}
//獲得所有的頭和對應(yīng)的值
e = request.getHeaderNames();
while(e.hasMoreElements()){
String name = (String) e.nextElement();
String value = request.getHeader(name);
System.out.println(value);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
3.1.3獲得瀏覽器請求參數(shù)(即瀏覽器提交的數(shù)據(jù))
package cn.itcast.request;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String value = request.getParameter("name");
System.out.println(value);
String[] values = request.getParameterValues("name");
//注意這里必須判斷values是否為空藕漱,否則在沒有參數(shù)的時(shí)候會出現(xiàn)異常
for(int i = 0; values != null && i < values.length; i++){
System.out.println(values[i]);
}
//獲取所有參數(shù)名稱欲侮,并根據(jù)名稱獲取其值,如:
//http://localhost:8080/ResAndReq/servlet/RequestDemo1?name=yj&like=ali
//得到name=yj&like=ali
Enumeration e = request.getParameterNames();
while(e.hasMoreElements()){
String name = (String) e.nextElement();
value = request.getParameter(name);
System.out.println(name + "=" + value);
}
//下面這種方式在框架中大量使用肋联,注意Map中第二個(gè)參數(shù)有可能是字符串或數(shù)組威蕉,所以使用String[]
Map<String, String[]> map = request.getParameterMap();
for(Map.Entry<String, String[]> me : map.entrySet()){
String name = me.getKey();
String[] v = me.getValue();
System.out.println(name + "=" + v);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
說明:對于表單提交過來的各種表單數(shù)據(jù),也可以通過上面的方式獲得橄仍。
3.1.4請求參數(shù)的中文亂碼問題
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//中文亂碼問題
public class RequestDemo4 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//post提交時(shí)亂碼解決方式:設(shè)置服務(wù)器打開請求數(shù)據(jù)時(shí)用的碼表韧涨,即request使用的碼表
//request.setCharacterEncoding("UTF-8");
String username = request.getParameter("username");
System.out.println(username);
//get提交時(shí)亂碼解決方式:先使用iso8859-1得到數(shù)據(jù),然后再使用正確的編碼轉(zhuǎn)換過來
byte[] source = username.getBytes("iso8859-1");
username = new String(source, "UTF-8");
System.out.println(username);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
form.html
<!DOCTYPE html>
<html>
<head>
<title>form.html</title>
<meta name="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="/ResAndReq/servlet/RequestDemo4" method="get">
用戶名:<input type="text" name="username"/><br/>
密碼:<input type="password" name="password"/><br/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
注意:使用post方式提交表單數(shù)據(jù)時(shí)需要注意幾點(diǎn):
(1)在html中我們使用<meta name="content-type" content="text/html; charset=UTF-8">規(guī)定保存此文件的格式侮繁,我們可以選中文件右鍵àProperties可以在下面的Default處看到文件的編碼格式虑粥,是和我們設(shè)置的編碼一致的。
(2)表單在提交的時(shí)候我們需要查看瀏覽器使用哪張碼表打開此表單宪哩,如果使用GBK打開此表單娩贷,那么填寫在此表單中提交的數(shù)據(jù)也將使用GBK編碼,提交到服務(wù)器之后request.getParameter默認(rèn)會使用iso8859-1碼表將獲得的數(shù)據(jù)轉(zhuǎn)換成字符串锁孟,此時(shí)會出現(xiàn)亂碼彬祖。我們可以使用request.setCharacterEncoding("GBK");將Request使用的碼表換成GBK,這樣和瀏覽器使用的編碼就一致了罗岖。
涧至??桑包?南蓬??哑了?赘方??弱左?窄陡??拆火?跳夭?涂圆??币叹?润歉??颈抚?踩衩??贩汉?驱富??匹舞?褐鸥??赐稽?晶疼??又憨??锭吨?蠢莺?
使用get方式提交表單數(shù)據(jù)時(shí)需要注意:
當(dāng)使用get方式提交表單數(shù)據(jù)時(shí),設(shè)置Request編碼是無效的零如,于是我們需要先使用iso8859碼表得到亂碼數(shù)據(jù)躏将,然后再使用何時(shí)的碼表將亂碼轉(zhuǎn)換成正確的文本數(shù)據(jù)。這是看視頻教程中是這樣解決的考蕾,但是在自己本地卻不好使祸憋,當(dāng)我的網(wǎng)頁使用UTF-8打開時(shí)提交的數(shù)據(jù)能正確顯示,但是如果使用GBK打開則不能正確顯示肖卧。也就是網(wǎng)頁使用UTF-8編碼的數(shù)據(jù)提交才能正確顯示蚯窥,不是默認(rèn)去查iso8859-1嗎,這難道是tomcat的原因塞帐?拦赠??葵姥?
還有個(gè)問題沒有解決:就是當(dāng)直接使用地址http://localhost:8080/ResAndReq/servlet/RequestDemo4?username='中國' 訪問服務(wù)器時(shí)荷鼠,不需要設(shè)置任何編碼就可以顯示正確的文本。而且不管瀏覽器使用什么編碼我們在地址欄中都可以看到正確的文本榔幸。URL其實(shí)對于漢字是直接使用的ASCII碼允乐,只是每個(gè)字的編碼前加上一個(gè)%號矮嫉??牍疏?蠢笋?
最后還可以更改服務(wù)器配置文件,在server.xml中的<Connector>標(biāo)簽的最后加上一個(gè)屬性:URIEncoding="UTF-8"即可麸澜。這時(shí)什么都不需要設(shè)置了直接使用String username = request.getParameter("username");這種方式一般不適用.這里我們還有一種靈活的方式,在<Connector>標(biāo)簽添加下面這個(gè)屬性將useBodyEncodingForURI屬性設(shè)置為true挺尿,那么如果我們r(jià)equest.setCharacterEncoding("UTF-8");之后連接器就使用什么編碼。不管是什么方式炊邦,但是更改服務(wù)器的配置文件一般不推薦编矾。
3.1.5 request對象實(shí)現(xiàn)請求轉(zhuǎn)發(fā)
請求轉(zhuǎn)發(fā)是指一個(gè)web資源收到客戶端請求后,通知服務(wù)器去調(diào)用另外一個(gè)web資源進(jìn)行處理馁害。請求轉(zhuǎn)發(fā)的應(yīng)用場景有如MVC設(shè)計(jì)模式窄俏。Request對象提供一個(gè)getRequestDispatcher方法,該方法返回一個(gè)RequestDespatcher對象碘菜,調(diào)用這個(gè)對象的forward方法可以實(shí)現(xiàn)請求轉(zhuǎn)發(fā)凹蜈。
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo5 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data = "aaa";
//注意:在進(jìn)行數(shù)據(jù)傳遞的時(shí)候一定不能使用ServletContext對象作為容器,因?yàn)? //此容器是共享的或全局的忍啸,在并發(fā)訪問的時(shí)候會出現(xiàn)錯誤仰坦,后面的數(shù)據(jù)可能會將前面
//的數(shù)據(jù)覆蓋。
//this.getServletContext().setAttribute("data", data);//把數(shù)據(jù)傳給jsp處理
//這里最好使用request傳遞數(shù)據(jù)计雌,因?yàn)闉g覽器的每次請求都會產(chǎn)生一個(gè)自己的request對象
request.setAttribute("data", data);
//轉(zhuǎn)發(fā)
this.getServletContext().getRequestDispatcher("/text.jsp").forward(request, response);
/*RequestDispatcher rd = request.getRequestDispatcher("/text.jsp");
rd.forward(request, response);*/
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
注意:在服務(wù)器啟動后只會產(chǎn)生一個(gè)ServletContext對象悄晃,這個(gè)對象是共享的,而每次請求都會產(chǎn)生一個(gè)新的request和response對象凿滤,而在轉(zhuǎn)發(fā)的過程中是不會創(chuàng)建新的request和response對象妈橄,只是會調(diào)用多個(gè)servlet,后面的servlet會將之前寫入的數(shù)據(jù)清空翁脆。
3.2 request對象
此對象同時(shí)也是一個(gè)域?qū)ο螅ㄈ萜鳎┚祢荆皇沁@個(gè)域?qū)ο笫轻槍σ淮螢g覽器請求,而不是像ServletContext對象是針對一個(gè)web應(yīng)用反番,所以聲明周期會短沙热,資源也不是共享。開發(fā)人員通過request對象在實(shí)現(xiàn)轉(zhuǎn)發(fā)時(shí)罢缸,把數(shù)據(jù)通過request對象帶給其他web資源處理校读。
3.2.1請求轉(zhuǎn)發(fā)的細(xì)節(jié)
forward方法用于將請求轉(zhuǎn)發(fā)到RequestDispatcher對象封裝的資源。如果在調(diào)用forward方法之前祖能,在servlet程序中寫入的部分內(nèi)容已經(jīng)被真正地傳遞到了客戶端歉秫,forward方法將拋出IIIegalStateException異常。如果在調(diào)用forward方法之前向servlet引擎的緩沖區(qū)(response)中寫入了內(nèi)容养铸,只要寫入到緩沖區(qū)中的內(nèi)容還沒有被真正輸出到客戶度雁芙,forward方法就可以被正常執(zhí)行轧膘,原來寫入到輸出緩沖區(qū)中的內(nèi)容將被清空,但是兔甘,已經(jīng)寫入到HttpServletResponse對象中的響應(yīng)頭字段信息保持有效谎碍,不會被清空或覆蓋。
3.2.2請求重定向和請求轉(zhuǎn)發(fā)的區(qū)別:
(1)一個(gè)web資源收到客戶端請求后洞焙,通知服務(wù)器去調(diào)用另外一個(gè)web資源進(jìn)行處理蟆淀,稱之為請求轉(zhuǎn)發(fā)。這里的兩個(gè)servlet共享一個(gè)request和response對象澡匪。同時(shí)地址欄不會發(fā)生變化熔任。
(2)一個(gè)web資源收到客戶端請求后,通知瀏覽器去訪問另外一個(gè)web資源唁情,稱之為請求重定向疑苔。地址欄會發(fā)生變化。
(3)RequestDispatcher.forward方法只能將請求轉(zhuǎn)發(fā)給同一個(gè)web應(yīng)用中的組件(即多個(gè)servlet)甸鸟;而HttpServletResponse.sendRedirect方法可以重定向到同一個(gè)站點(diǎn)上的其他應(yīng)用程序中的資源(多個(gè)web應(yīng)用)惦费,甚至是使用絕對URL重定向到其他站點(diǎn)的資源。
(4)調(diào)用HttpServletResponse.sendRedirect方法重定向的訪問過程結(jié)束后抢韭,瀏覽器地址欄中顯示的URL地址會發(fā)生變化薪贫,由初始的URL地址變成重定向的目標(biāo)URL;調(diào)用RequestDispatcher.forward方法的請求轉(zhuǎn)發(fā)過程結(jié)束后刻恭,瀏覽器地址欄保持初始的URL地址后雷。
(5)HttpServletResponse.sendRedirect方法對瀏覽器的請求直接做出響應(yīng),響應(yīng)的結(jié)果就是告訴瀏覽器去重新發(fā)出對另外一個(gè)URL的訪問請求吠各;RequestDispatcher.forward方法在服務(wù)器端內(nèi)部將請求轉(zhuǎn)發(fā)給另外一個(gè)資源(servlet),瀏覽器只知道發(fā)出了請求并得到了響應(yīng)結(jié)果勉抓,并不知道在服務(wù)器內(nèi)部發(fā)生了轉(zhuǎn)發(fā)行為贾漏。
(6)RequestDispatcher.forward方法調(diào)用者與被調(diào)用者之間共享相同的request和response對象,它們屬于同一個(gè)訪問請求和響應(yīng)過程藕筋;而HttpServletResponse.sendRedirect方法調(diào)用者與被調(diào)用者使用各自的request和response對象纵散,它們屬于兩個(gè)獨(dú)立的訪問請求和響應(yīng)過程。
(7)include方法
RequestDispatcher.include方法用于將RequestDispatcher對象封裝的資源內(nèi)容作為當(dāng)前響應(yīng)內(nèi)容的一部分包含進(jìn)來隐圾,從而實(shí)現(xiàn)可編程的服務(wù)器包含功能伍掀。被包含的servlet程序不能改變響應(yīng)消息的狀態(tài)碼和響應(yīng)頭,如果它里面存在這樣的語句暇藏,這些語句的執(zhí)行結(jié)果將被忽略蜜笤。
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo6 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.getRequestDispatcher("/servlet/HeadServlet").include(request, response);
response.getWriter().write("<br/>aaa<br/>");
request.getRequestDispatcher("/servlet/FootServlet").include(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
網(wǎng)頭
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HeadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("這是網(wǎng)頭");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
網(wǎng)腳
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FootServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("這是網(wǎng)腳");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}