Javaweb學習總結(二)—— HttpServletResponse物件
阿新 • • 發佈:2018-12-30
HttpServletResponse物件、用Servlet生成驗證碼圖片。
web伺服器根據每一次請求,建立相對應的請求物件request、和代表響應的物件response。
- 通過請求物件,我們獲取資料。
- 通過響應物件,我們傳送資料。
HttpServletResponse物件中設定響應頭的相關方法
HttpServletResponse物件常見應用
使用OutputStream流向客戶端瀏覽器輸出中文資料
- 在伺服器端,資料是以哪個碼錶輸出的,那麼就要控制客戶端瀏覽器以相應的碼錶開啟,比如:outputStream.write(“中國”.getBytes(“UTF-8”));使用OutputStream流向客戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出,此時就要控制客戶端瀏覽器以UTF-8的編碼開啟,否則顯示的時候就會出現中文亂碼,那麼在伺服器端如何控制客戶端瀏覽器以以UTF-8的編碼顯示資料呢?可以通過設定響應頭控制瀏覽器的行為,例如:response.setHeader(“content-type”, “text/html;charset=UTF-8”);通過設定響應頭控制瀏覽器以UTF-8的編碼顯示資料。
範例:使用OutputStream流向客戶端瀏覽器輸出"中國"這兩個漢字
package gacl.response.study;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ResponseDemo01 extends HttpServlet {
private static final long serialVersionUID = 4312868947607181532L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
outputChineseByOutputStream(response); //使用OutputStream流輸出中文
}
/**
* 使用OutputStream流輸出中文
* @param request
* @param response
* @throws IOException
*/
public void outputChineseByOutputStream(HttpServletResponse response) throws IOException{
/**使用OutputStream輸出中文注意問題:
* 在伺服器端,資料是以哪個碼錶輸出的,那麼就要控制客戶端瀏覽器以相應的碼錶開啟,
* 比如:outputStream.write("中國".getBytes("UTF-8"));//使用OutputStream流向客戶端瀏覽器輸出中文,以UTF-8的編碼進行輸出
* 此時就要控制客戶端瀏覽器以UTF-8的編碼開啟,否則顯示的時候就會出現中文亂碼,那麼在伺服器端如何控制客戶端瀏覽器以以UTF-8的編碼顯示資料呢?
* 可以通過設定響應頭控制瀏覽器的行為,例如:
* response.setHeader("content-type", "text/html;charset=UTF-8");//通過設定響應頭控制瀏覽器以UTF-8的編碼顯示資料
*/
String data = "中國";
OutputStream outputStream = response.getOutputStream();//獲取OutputStream輸出流
response.setHeader("content-type", "text/html;charset=UTF-8");//通過設定響應頭控制瀏覽器以UTF-8的編碼顯示資料,如果不加這句話,那麼瀏覽器顯示的將是亂碼
/**
* data.getBytes()是一個將字元轉換成位元組陣列的過程,這個過程中一定會去查碼錶,
* 如果是中文的作業系統環境,預設就是查詢查GB2312的碼錶,
* 將字元轉換成位元組陣列的過程就是將中文字元轉換成GB2312的碼錶上對應的數字
* 比如: "中"在GB2312的碼錶上對應的數字是98
* "國"在GB2312的碼錶上對應的數字是99
*/
/**
* getBytes()方法如果不帶引數,那麼就會根據作業系統的語言環境來選擇轉換碼錶,如果是中文作業系統,那麼就使用GB2312的碼錶
*/
byte[] dataByteArr = data.getBytes("UTF-8");//將字元轉換成位元組陣列,指定以UTF-8編碼進行轉換
outputStream.write(dataByteArr);//使用OutputStream流向客戶端輸出位元組陣列
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
使用PrintWriter流向客戶端瀏覽器輸出中文資料
- 在獲取PrintWriter輸出流之前首先使用"response.setCharacterEncoding(charset)“設定字元以什麼樣的編碼輸出到瀏覽器,如:response.setCharacterEncoding(“UTF-8”);設定將字元以"UTF-8"編碼輸出到客戶端瀏覽器,然後再使用response.getWriter();獲取PrintWriter輸出流,這兩個步驟不能顛倒
注:使用meta設定HTML頁面的相關屬性
2
out.write(”");
等同於response.setHeader(“content-type”, “text/html;charset=UTF-8”);
使用OutputStream或者PrintWriter向客戶端瀏覽器輸出數字
在開發過程中,如果希望伺服器輸出什麼瀏覽器就能看到什麼,那麼在伺服器端都要以字串的形式進行輸出。
/**
* 使用OutputStream流輸出數字1
* @param request
* @param response
* @throws IOException
*/
public void outputOneByOutputStream(HttpServletResponse response) throws IOException{
response.setHeader("content-type", "text/html;charset=UTF-8");
OutputStream outputStream = response.getOutputStream();
outputStream.write("使用OutputStream流輸出數字1:".getBytes("UTF-8"));
//outputStream.write(1);
outputStream.write((1+"").getBytes());
}
1+""這一步是將數字1和一個空字串相加,這樣處理之後,數字1就變成了字串1了,然後再將字串1轉換成位元組陣列使用OutputStream進行輸出。 對於PrintWriter來說也一樣。
檔案下載
檔案下載功能的實現思路:
- 獲取要下載的檔案的絕對路徑
- 獲取要下載的檔名
- 設定content-disposition響應頭控制瀏覽器以下載的形式開啟檔案
- 獲取要下載的檔案輸入流
- 建立資料緩衝區
- 通過response物件獲取OutputStream流
- 將FileInputStream流寫入到buffer緩衝區
- 使用OutputStream將緩衝區的資料輸出到客戶端瀏覽器
package gacl.response.study;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author gacl
* 檔案下載
*/
public class ResponseDemo02 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
downloadFileByOutputStream(response);//下載檔案,通過OutputStream流
}
/**
* 下載檔案,通過OutputStream流
* @param response
* @throws FileNotFoundException
* @throws IOException
*/
private void downloadFileByOutputStream(HttpServletResponse response)
throws FileNotFoundException, IOException {
//1.獲取要下載的檔案的絕對路徑
String realPath = this.getServletContext().getRealPath("/download/1.JPG");
//2.獲取要下載的檔名
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//3.設定content-disposition響應頭控制瀏覽器以下載的形式開啟檔案
response.setHeader("content-disposition", "attachment;filename="+fileName);
//4.獲取要下載的檔案輸入流
InputStream in = new FileInputStream(realPath);
int len = 0;
//5.建立資料緩衝區
byte[] buffer = new byte[1024];
//6.通過response物件獲取OutputStream流
OutputStream out = response.getOutputStream();
//7.將FileInputStream流寫入到buffer緩衝區
while ((len = in.read(buffer)) > 0) {
//8.使用OutputStream將緩衝區的資料輸出到客戶端瀏覽器
out.write(buffer,0,len);
}
in.close();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
範例:使用Response實現中文檔案下載
- 下載中文檔案時,需要注意的地方就是中文檔名要使用URLEncoder.encode方法進行編碼(URLEncoder.encode(fileName, “字元編碼”)),否則會出現檔名亂碼。
package gacl.response.study;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author gacl
* 檔案下載
*/
public class ResponseDemo02 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
downloadChineseFileByOutputStream(response);//下載中文檔案
}
/**
* 下載中文檔案,中文檔案下載時,檔名要經過URL編碼,否則會出現檔名亂碼
* @param response
* @throws FileNotFoundException
* @throws IOException
*/
private void downloadChineseFileByOutputStream(HttpServletResponse response)
throws FileNotFoundException, IOException {
String realPath = this.getServletContext().getRealPath("/download/張家界國家森林公園.JPG");//獲取要下載的檔案的絕對路徑
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);//獲取要下載的檔名
//設定content-disposition響應頭控制瀏覽器以下載的形式開啟檔案,中文檔名要使用URLEncoder.encode方法進行編碼,否則會出現檔名亂碼
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
InputStream in = new FileInputStream(realPath);//獲取檔案輸入流
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);
}
}
注:
- 編寫檔案下載功能時推薦使用OutputStream流,避免使用PrintWriter流,因為OutputStream流是位元組流,可以處理任意型別的資料,而PrintWriter流是字元流,只能處理字元資料,如果用字元流處理位元組資料,會導致資料丟失。
生成隨機圖片用作驗證碼
package gacl.response.study;
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 ResponseDemo03 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setHeader("refresh", "5");//設定refresh響應頭控制瀏覽器每隔5秒鐘定時重新整理網頁一次
//1.在記憶體中建立一張圖片
BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//2.得到圖片
//Graphics g = image.getGraphics();
Graphics2D g = (Graphics2D)image.getGraphics();
g.setColor(Color.WHITE);//設定圖片的背景色
g.fillRect(0, 0, 80, 20);//填充背景色
//3.向圖片上寫資料
g.setColor(Color.BLUE);//設定圖片上字型的顏色
g.setFont(new Font(null, Font.BOLD, 20));
g.drawString(makeNum(), 0, 20);
//4.設定響應頭控制瀏覽器瀏覽器以圖片的方式開啟
response.setContentType("image/jpeg");//等同於response.setHeader("Content-Type", "image/jpeg");
//5.設定響應頭控制瀏覽器不快取圖片資料
response.setDateHeader("expries", -1);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
//6.將圖片寫給瀏覽器
ImageIO.write(image, "jpg", response.getOutputStream());
}
/**
* 生成隨機數字
* @return
*/
private String makeNum(){
Random random = new Random();
String num = random.nextInt(9999999)+"";
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 7-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);
}
}
通過response實現請求重定向
package gacl.response.study;
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 ResponseDemo04 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
/**
* 1.呼叫sendRedirect方法實現請求重定向,
* sendRedirect方法內部呼叫了
* response.setHeader("Location", "/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
* response.setStatus(HttpServletResponse.SC_FOUND);//設定302狀態碼,等同於response.setStatus(302);
*/
response.sendRedirect("/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
//2.使用response設定302狀態碼和設定location響應頭實現重定向實現請求重定向
//response.setHeader("Location", "/JavaWeb_HttpServletResponse_Study_20140615/index.jsp");
//response.setStatus(HttpServletResponse.SC_FOUND);//設定302狀態碼,等同於response.setStatus(302);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
web工程中URL地址
"/"代表當前web工程的常見應用場景
①.ServletContext.getRealPath(String path)獲取資源的絕對路徑
②.在伺服器端forward到其他頁面(請求轉發)
③.使用include指令或者jsp:include標籤引入頁面
"/"代表webapps目錄的常見應用場景
①.使用sendRedirect實現請求重定向
②.使用超連結跳轉
③.Form表單提交
response細節問題
- getOutputStream和getWriter這兩個方法互相排斥,呼叫了其中的任何一個方法後,就不能再呼叫另一方法。(本人已經入過坑)
- Serlvet的service方法結束後,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流物件是否已經呼叫過close方法,如果沒有,Servlet引擎將呼叫close方法關閉該輸出流物件。