1. 程式人生 > >Javaweb學習總結(二)—— HttpServletResponse物件

Javaweb學習總結(二)—— HttpServletResponse物件

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來說也一樣。

檔案下載

檔案下載功能的實現思路:

  1. 獲取要下載的檔案的絕對路徑
  2. 獲取要下載的檔名
  3. 設定content-disposition響應頭控制瀏覽器以下載的形式開啟檔案
  4. 獲取要下載的檔案輸入流
  5. 建立資料緩衝區
  6. 通過response物件獲取OutputStream流
  7. 將FileInputStream流寫入到buffer緩衝區
  8. 使用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方法關閉該輸出流物件。

通過Servlet建立隨機圖片

https://www.cnblogs.com/xdp-gacl/p/3798190.html