Servlet第三篇(response;request)
Tomcat收到客戶端的http請求,會針對每一次請求,分別創建一個代表請求的request對象、和代表響應的response對象
那麽我們獲取瀏覽器提交過來的數據,找request對象即可。response對象代表http響應,那麽我們向瀏覽器輸出數據,找response對象即可。
response對象
什麽是HttpServletResponse對象?
http響應由狀態行、實體內容、消息頭、一個空行組成。HttpServletResponse對象就封裝了http響應的信息。
HttpServletResponse的應用
輸出utf-8中文字符
getOutputStream().write(xxx.getBytes())
調用getOutputStream()方法向瀏覽器輸出數據
print
Tomcat使用IOS 8859-1編碼對其進行轉換,“中國”根本對ISO 8859-1編碼不支持。
write
"你好呀我是中國".getBytes()這句代碼在轉成byte[]數組的時候默認查的是gb2312編碼,而"你好呀我是中國"支持gb2312編碼,所以可以正常顯示出來。
- 設置頭信息,告訴瀏覽器我回送的數據編碼是utf-8的
response.setHeader("Content-Type", "text/html;charset=UTF-8");
- 使用meta標簽模擬http消息頭,告訴瀏覽器回送數據的編碼和格式
servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
- getwrite().write(xxx)
使用getWriter()顯示中文數據,只需要一個方法就搞掂了!
response.setContentType("text/html;charset=UTF-8")(設置中文碼表和瀏覽器)把response.setCharacterEncoding("UTF-8")(設置中文碼表)的工作也做了
調用getWriter()方法向瀏覽器輸出數據
對於getWriter()方法而言,是Writer的子類,那麽只能向瀏覽器輸出字符數據,不能輸出二進制數據
實現文件下載
java的文件上傳下載都是通過io流來完成的,既然要下載圖片,首先要能夠讀取到它
//獲取到資源的路徑
String path = this.getServletContext().getRealPath("/download/1.png");
//讀取資源
FileInputStream fileInputStream = new FileInputStream(path);
//獲取到文件名,路徑在電腦上保存是\\形式的。
String fileName = path.substring(path.lastIndexOf("\\") + 1);
告訴瀏覽器,我要下載這個文件
//設置消息頭,告訴瀏覽器,我要下載1.png這個圖片
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
為了解決文件名亂碼,我們要進行URL編碼,代碼如下:
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
將讀取到的內容回送給瀏覽器
//把讀取到的資源寫給瀏覽器
int len = 0;
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();
while ((len = fileInputStream.read(bytes)) > 0) {
servletOutputStream.write(bytes, 0, len);
}
//關閉資源
servletOutputStream.close();
fileInputStream.close();
實現自動刷新
讓瀏覽器實現自動刷新,那肯定又是修改消息頭了。
//每3秒自動刷新網頁一次
response.setHeader("Refresh", "3");
設置緩存
瀏覽器本身就存在著緩存機制
禁止緩存的功能
//瀏覽器有三消息頭設置緩存,為了兼容性!將三個消息頭都設置了
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
實現數據壓縮
GZIPOutputStream寫數據的時候,是把數據寫到ByteArrayOutputStream上的,等會還要把數據取出來,再寫給瀏覽器
//告訴瀏覽器這是gzip壓縮的數據
response.setHeader("Content-Encoding","gzip");
生出隨機圖片
要生成一張圖片,java提供了BufferedImage類供我們使用
//在內存中生成一張圖片,寬為80,高為20,類型是RGB
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//獲取到這張圖片
Graphics graphics = bufferedImage.getGraphics();
//往圖片設置顏色和字體
graphics.setColor(Color.BLUE);
graphics.setFont(new Font(null, Font.BOLD, 20));
//往圖片上寫數據,先寫個12345,橫坐標是0,縱坐標是20【高度】
graphics.drawString("12345", 0, 20);
把圖片寫給瀏覽器,java又提供了圖片流【ImageIO】給我們使用
//把圖片傳進去,類型是jpg,寫給瀏覽器
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
重定向跳轉
//重定向到index.jsp頁面
response.sendRedirect("/zhongfucheng/index.jsp");
其實sendRedirect()方法就是對setStatus(302)和setHeader()進行封裝,原理就是setStatus()和setHeader()
getWriter和getOutputStream細節
getWriter()和getOutputStream()兩個方法不能同時調用。如果同時調用就會出現異常
Servlet程序向ServletOutputStream或PrintWriter對象中寫入的數據將被Servlet引擎從response裏面獲取,Servlet引擎將這些數據當作響應消息的正文,然後再與響應狀態行和各響應頭組合後輸出到客戶端。
Servlet的serice()方法結束後【也就是doPost()或者doGet()結束後】,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經調用過close方法,如果沒有,Servlet引擎將調用close方法關閉該輸出流對象.
request對象
什麽是HttpServletRequest
HttpServletRequest對象代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶這些信息。
HttpServletRequest常用方法
獲得客戶機【瀏覽器】信息
getRequestURL方法返回客戶端發出請求時的完整URL。
getRequestURI方法返回請求行中的資源名部分。
getQueryString 方法返回請求行中的參數部分。
getPathInfo方法返回請求URL中的額外路徑信息。額外路徑信息是請求URL中的位於Servlet的路徑之後和查詢參數之前的內容,它以“/”開頭。
getRemoteAddr方法返回發出請求的客戶機的IP地址
getRemoteHost方法返回發出請求的客戶機的完整主機名
getRemotePort方法返回客戶機所使用的網絡端口號
getLocalAddr方法返回WEB服務器的IP地址。
getLocalName方法返回WEB服務器的主機名
獲得客戶機請求頭
getHeader方法
getHeaders方法
getHeaderNames方法
獲得客戶機請求參數(客戶端提交的數據)
getParameter方法
getParameterValues(String name)方法
getParameterNames方法
getParameterMap方法
HttpServletRequest應用
防盜鏈
獲取Referer這個消息頭,判斷Referer是不是從我的首頁來的。如果不是從我的首頁來的,跳轉回我的首頁。
String referer=request.getHeader("Referer");
if(referer== null||!referer.contains("http://localhost:8088/firstServlet/NewSvlt")){
response.sendRedirect("/firstServlet/NewSvlt");
return;
表單提交數據【通過post方式提交數據】
request.getParameter()
request.getParameterValues()
get方式提交數據
通過超鏈接將數據帶給瀏覽器
使用超鏈接將數據帶給瀏覽器
sendRedirect()
sendRedirect("servlet的地址?參數名="+參數值&"參數名=" +參數值);
中文亂碼問題
首先我們來看一下post方法是怎麽進行參數傳遞的。當我們點擊提交按鈕的時候,數據封裝進了Form Data中,http請求中把實體主體帶過去了【傳輸的數據稱之為實體主體】,既然request對象封裝了http請求,所以request對象可以解析到發送過來的數據,於是只要把編碼設置成UTF-8就可以解決亂碼問題了。
而get方式不同,它的數據是從消息行帶過去的,沒有封裝到request對象裏面,所以使用request設置編碼是無效的。
Tomcat默認的編碼是ISO 8859-1,那麽get方式由消息體帶過去給瀏覽器的時候肯定是用ISO 8859-1編碼了
- 手工轉換
- 設置Tomcat
在8080端口的Connector上加入 URIEncoding="utf-8",設置Tomcat的訪問該端口時的編碼為utf-8,從而解決亂碼,這種改法是固定使用UTF-8編碼的
當然也有另一種改服務器編碼的方式。設置Tomcat的訪問該端口時的編碼為頁面的編碼 useBodyEncodingForURI="true",這種改法是隨著頁面的編碼而變。
實現轉發
request的getRequestDispatcher.forward(request,response)實現轉發
(RequestDispatcher還有另外一個方法include(),該方法可以實現包含一般網頁的頭部和尾部是不需要改變的。如果我們多個地方使用Servlet輸出網頭和網尾的話,需要把代碼重新寫一遍。而使用RequestDispatcher的include()方法就可以實現包含網頭和網尾的效果了。)
request也可以稱之為域對象,只不過ServletContext的域是整個web應用,而request的域僅僅代表一次http請求 請求轉發的細節 如果在調用forward方法之前,在Servlet程序中寫入的部分內容已經被真正地傳送到了客戶端,forward方法將拋出IllegalStateException異常。 也就是說:不要在轉發之前寫數據給瀏覽器 如果在調用forward方法之前向Servlet引擎的緩沖區中寫入了內容,只要寫入到緩沖區中的內容還沒有被真正輸出到客戶端,forward方法就可以被正常執行,原來寫入到輸出緩沖區中的內容將被清空,但是,已寫入到HttpServletResponse對象中的響應頭字段信息保持有效。
轉發和重定向的區別
實際發生位置不同,地址欄不同
轉發是發生在服務器的
轉發是由服務器進行跳轉的,細心的朋友會發現,在轉發的時候,瀏覽器的地址欄是沒有發生變化的,在我訪問Servlet111的時候,即使跳轉到了Servlet222的頁面,瀏覽器的地址還是Servlet111的。也就是說瀏覽器是不知道該跳轉的動作,轉發是對瀏覽器透明的。通過上面的轉發時序圖我們也可以發現,實現轉發只是一次的http請求,一次轉發中request和response對象都是同一個。這也解釋了,為什麽可以使用request作為域對象進行Servlet之間的通訊。
重定向是發生在瀏覽器的
重定向是由瀏覽器進行跳轉的,進行重定向跳轉的時候,瀏覽器的地址會發生變化的。曾經介紹過:實現重定向的原理是由response的狀態碼和Location頭組合而實現的。這是由瀏覽器進行的頁面跳轉實現重定向會發出兩個http請求,request域對象是無效的,因為它不是同一個request對象
用法不同
給服務器用的直接從資源名開始寫(轉發),給瀏覽器用的要把應用名寫上(重定向)
能夠去往的URL的範圍不一樣
轉發是服務器跳轉只能去往當前web應用的資源
重定向是服務器跳轉,可以去往任何的資源
傳遞數據的類型不同
轉發的request對象可以傳遞各種類型的數據,包括對象
重定向只能傳遞字符串
跳轉的時間不同
轉發時:執行到跳轉語句時就會立刻跳轉
重定向:整個頁面執行完之後才執行跳轉
轉發和重定向使用哪一個?
轉發是帶著轉發前的請求的參數的。重定向是新的請求。
典型的應用場景:
轉發: 訪問 Servlet 處理業務邏輯,然後 forward 到 jsp 顯示處理結果,瀏覽器裏 URL 不變
重定向: 提交表單,處理成功後 redirect 到另一個 jsp,防止表單重復提交,瀏覽器裏 URL 變了
Servlet第三篇(response;request)