JavaEE學習日誌(五十二): Response對象,文件下載案例,驗證碼案例

JavaEE學習日誌持續更新----> 必看!JavaEE學習路線(文章總彙)

Response對象

負責對瀏覽器進行響應
HttpServletResponse接口繼承自ServletResponse接口
使用子接口HttpServletResponse接口,此接口對象由tomcat引擎提供。

Response設置響應行

設置狀態碼:setStatus(int 狀態碼)

response.setStatus(500);

Response設置響應頭

HTTP協議的響應頭,數據格式爲鍵值對k:v
包含指導性信息,指導客戶端

方法

  • addHeader(String add,String value)添加,實現一個鍵對應多個值
  • addIntHeader(String add,int value)
  • addDataHeader(String key,long l)
 response.addHeader("heima","java");
 response.addIntHeader("heima2",2);
 response.addDateHeader("heima3",System.currentTimeMillis());

在這裏插入圖片描述

  • setHeader(String add,String value)設置,覆蓋原來的鍵(用這個)
  • setIntHeader(String add,int value)
  • setDataHeader(String key,long l)
 response.setHeader("heima","javaee");

在這裏插入圖片描述

Response設置響應體

HTTP的響應體,就是頁面的正文部分

方法

  • getWriter() 返回值是打印流PrintWriter
PrintWriter pw = response.getWriter();
        
pw.write("hehe");
pw.print("xixi");

write()print()的區別
write():使用字符串數據,沒有差別;輸出的是整數,查詢編碼表
print():無論是什麼,原樣打印

響應中的中文亂碼問題
產生亂碼的原因:編碼和解碼不一致。響應數據時,沒有直接寫在客戶端,而是寫在response對象緩衝區,而緩衝區使用的編碼表是ios8859-1拉丁文編碼。

解決方法一:
設置response對象緩衝區的編碼表,並通知瀏覽器,使用utf-8解碼
方法:setCharacterEncoding("編碼表")
這種方法谷歌瀏覽器好像不行,其他瀏覽器可以。

response.setCharacterEncoding("utf-8");
PrintWriter pw = response.getWriter();
pw.write("<meta charset='utf-8'>");
pw.write("你好");

解決方法二(就用它):
方法:setContentType("text/html;charset=UTF-8")

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.write("你好");
    }
  • getOutputStream() 返回字節輸出流OutputStream
    返回字節流,響應非文本類型的數據

在Web目錄下添加a.jgp文件,輸出a.jpg

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            響應非文本類型數據
         */
        //獲取圖片的絕對路徑
        String aFile = getServletContext().getRealPath("a.jpg");
        FileInputStream fis = new FileInputStream(aFile);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        fis.close();
    }

重定向(重點)

概念
在這裏插入圖片描述
接收瀏覽器的請求,對瀏覽器進行響應,瀏覽器進行重新的定向:

  1. 302狀態碼
  2. 重定向資源的地址:響應頭

代碼示例:servlet1重定向到servlet2

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            接收瀏覽器的請求,對瀏覽器進行響應
                瀏覽器進行重新的定向:
                    302狀態碼
                    重定向資源的地址:響應頭
         */
        response.setStatus(302);
        response.setHeader("location","/Web03/servlet2");



    }

簡便寫法:response.sendRedirect("/Web03/servlet2");

重定向到百度

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            接收瀏覽器的請求,對瀏覽器進行響應
                瀏覽器進行重新的定向:
                    302狀態碼
                    重定向資源的地址:響應頭
         */
        /*response.setStatus(302);
        response.setHeader("location","/Web03/servlet2");*/

        response.sendRedirect("http://www.baidu.com");



    }

Response注意事項

  1. 重定向後,不要再寫代碼,沒有意義
  2. 不能多次重定向
  3. getWriter()字符流和getOutputStream()字節流互斥,只能選擇一個使用。(因爲當servlet執行完成之後,緩衝區纔會發送數據,那麼緩衝區到底是字符的,還是字節的)

文件下載

客戶端瀏覽器從服務器下載文件
實現:超鏈接,連接的地址是服務器端文件的路徑

會出現一個問題:當瀏覽器識別文件,不是下載,直接打開運行

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        a:link{color: black}
        a:visited{color: black}
    </style>
</head>
<body>
    <!--超鏈接,實現文件下載
        連接的地址,服務器端需要下載的文件的路徑
    -->
    <a href="/Web03/download/a.flv">a.flv</a>
    <a href="/Web03/download/a.jpg">a.jpg</a>
    <a href="/Web03/download/a.mp3">a.mp3</a>
    <a href="/Web03/download/a.mp4">a.mp4</a>
    <a href="/Web03/download/a.txt">a.txt</a>
    <a href="/Web03/download/a.zip">a.zip</a>
</body>
</html>

所以需要編寫服務器端代碼,告訴瀏覽器下載,不要打開

關鍵代碼:告訴瀏覽器,此文件下載

response.setHeader("Content-Disposition","attachment;filename=a.jpg");

具體程序

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            通過服務器端下載,不要打開
            指導瀏覽器幹什麼:響應頭
            瀏覽器下載是HTTP協議規定
         */
        response.setHeader("Content-Disposition","attachment;filename=a.jpg");
        String aFile = getServletContext().getRealPath("download/a.jpg");
        FileInputStream fis = new FileInputStream(aFile);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] bytes = new byte[1024];
        while((len = fis.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        fis.close();
    }

前端

<!--超鏈接,連接地址不是文件,而是Servlet-->
<a href="/Web03/downLoad">a.jpg</a>

文件下載(中文文件名)

jdk8之前:直接導包使用

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /*
     * 編寫程序,通知瀏覽器請你下載,不要打開
     * 指導瀏覽器幹什麼,響應頭
     * 瀏覽器下載是HTTP協議規定
     */

    String agent = request.getHeader("User-Agent");
    String filename="美女.jpg";
    if (agent.contains("MSIE")) {
        // IE瀏覽器
        filename = URLEncoder.encode(filename, "utf-8");
        filename = filename.replace("+", " ");
    } else if (agent.contains("Firefox")) {
        // 火狐瀏覽器
        BASE64Encoder base64Encoder = new BASE64Encoder();
        filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
    } else {
        // 其它瀏覽器
        filename = URLEncoder.encode(filename, "utf-8");
    }
    response.setHeader("Content-Disposition","attachment;filename="+filename);
    String aFile = getServletContext().getRealPath("download/a.jpg");
    FileInputStream fis = new FileInputStream(aFile);
    OutputStream out = response.getOutputStream();
    int len = 0;
    byte[] bytes = new byte[1024];
    while ((len = fis.read(bytes))!=-1){
        out.write(bytes,0,len);
    }
    fis.close();
}

jdk8之後:需要下載Apache的commons-codec才能使用。

import org.apache.commons.codec.binary.Base64;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
            通過服務器端下載,不要打開
            指導瀏覽器幹什麼:響應頭
            瀏覽器下載是HTTP協議規定
         */

        String agent = request.getHeader("User-Agent");
        String filename="美女.jpg";
        if (agent.contains("MSIE")) {
            // IE瀏覽器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐瀏覽器
            Base64 base64 = new Base64();
            filename = "=?utf-8?B?" + base64.encodeBase64String(filename.getBytes("utf-8")) + "?=";
        } else {
            // 其它瀏覽器
            filename = URLEncoder.encode(filename, "utf-8");
        }

        response.setHeader("Content-Disposition","attachment;filename="+filename);
        String aFile = getServletContext().getRealPath("download/a.jpg");
        FileInputStream fis = new FileInputStream(aFile);
        OutputStream out = response.getOutputStream();
        int len = 0;
        byte[] bytes = new byte[1024];
        while((len = fis.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        fis.close();
    }

在這裏插入圖片描述

驗證碼

驗證碼的本質就是一個圖片,圖片裏面是一個隨機生產的字符串

生成驗證碼

public class CodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //  創建畫布
        int width = 120;
        int height = 40;
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //  獲得畫筆
        Graphics g = bufferedImage.getGraphics();
        //  填充背景顏色
        g.setColor(Color.white);
        g.fillRect(0, 0, width, height);
        //  繪製邊框
        g.setColor(Color.red);
        g.drawRect(0, 0, width - 1, height - 1);
        //  生成隨機字符
        //  準備數據
        String data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
        //  準備隨機對象
        Random r = new Random();
        //  聲明一個變量 保存驗證碼
        String code = "";
        //  書寫4個隨機字符
        for (int i = 0; i < 4; i++) {
            //  設置字體
            g.setFont(new Font("宋體", Font.BOLD, 28));
            //  設置隨機顏色
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

            String str = data.charAt(r.nextInt(data.length())) + "";
            g.drawString(str, 10 + i * 28, 30);

            //  將新的字符 保存到驗證碼中
            code = code + str;
        }
        //  繪製干擾線
        for (int i = 0; i < 6; i++) {
            //  設置隨機顏色
            g.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));

            g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
        }

        //  將驗證碼 打印到控制檯
        System.out.println(code);

        //  將驗證碼放到session中
        request.getSession().setAttribute("code_session", code);

        //  將畫布顯示在瀏覽器中
        ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
    }

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

}

前端

注意:頁面打開的時候,請求了服務器資源/Web03/code;點擊圖片的時候js函數中,發了請求/Web03/code。請求的資源沒有變化,服務器端程序也沒有變化,所以瀏覽器就會拿緩存

所以有要求:每次請求不一樣,添加參數

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
    實現驗證碼效果
    本質圖片:img src=屬性值是服務器資源CodeServlet
-->
<img src="/Web03/code" onclick="fnchange()" id="code">

<script type="text/javascript">
    function fnchange() {
        /*
            頁面打開的時候,請求了服務器資源/Web03/code
            點擊圖片的時候js函數中,發了請求/Web03/code
            請求的資源沒有變化,服務器端程序也沒有變化
            所以瀏覽器就拿了緩存

            所以有要求:每次請求不一樣,添加參數
         */

        //點擊圖片,修改src的屬性值
        var code = document.getElementById("code");
        var date = new Date().getTime();
        code.src="/Web03/code?a="+date;
    }
</script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章