1. 程式人生 > >深入學習請求響應(一)---response的應用

深入學習請求響應(一)---response的應用

概述

Web伺服器收到客戶端的http請求,會針對每一次請求,分別建立一個用於代表請求的request物件和代表響應的response物件。
request和response物件即然代表請求和響應,那我們要獲取客戶機提交過來的資料,只需要找request物件就行了;要向客戶機輸出資料,只需要找response物件就行了。

response的繼承結構

ServletResponse -- 通用的response。提供了一個響應應該具有最基本的屬性和方法。
    |-HttpServletResponse -- 在ServletResponse的基礎上針對於HTTP協議增加了很多強化的屬性和方法。

利用response向瀏覽器輸出一段資料

package me.zipstream.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 OutServlet extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // response.setContentType("text/html;charset=utf-8");//通知瀏覽器用u8來解碼 // response.getOutputStream().write("中國".getBytes("utf-8")); response.setCharacterEncoding("utf-8"
);//通知伺服器以u8來編碼。 //其實上面這句話可以省略,因為只要有下面這句話,伺服器就會預設使用u8來編碼。 response.setContentType("text/html; charset=utf-8");//通知瀏覽器以u8來解碼。 response.getWriter().write("中國"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

另外,這裡需要注意的是:
對於一次請求,Response的getOutputStream()方法和getWriter()方法互斥,只能呼叫其一,特別注意forward後(在請求轉發時)也不要違反這一規則。

利用response實現下載

package me.zipstream.response;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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 DownServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode("機械鍵盤.jpg", "utf-8"));

        InputStream in = new FileInputStream(this.getServletContext().getRealPath("1.jpg"));
        OutputStream out = response.getOutputStream();

        byte[] buf = new byte[1024];
        int len = 0;

        while ((len=in.read(buf))!=-1){
            out.write(buf, 0, len);
        }

        in.close();
    }

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



    /*
     * URL編碼與解碼的過程
     */
/*
    public static void main(String[] args) throws Exception {
        String str = "文明開化";
        String str2 = URLEncoder.encode(str, "utf-8");
        System.out.println(str2);

        String str3 = URLDecoder.decode("%E6%96%87%E6%98%8E%E5%BC%80%E5%8C%96", "utf-8");
        System.out.println(str3);
    }
*/

}

設定響應頭content-disposition為“attachment;filename=xxx.xxx”。
利用輸入流將檔案讀取進來,再利用Response獲取響應流輸出。
如果檔名為中文,一定要進行URL編碼,編碼所用的碼錶必須是utf-8。

注意:
service方法返回後,伺服器會自己檢查Response獲取的OutputStream()或者Writer()是否關閉,如果沒有關閉,伺服器自動幫你關閉,一般情況下不要自己關閉這兩個流。

利用response實現定時重新整理頁面

package me.zipstream.response;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RefreshServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //隔1s重新整理一次本頁
//      response.getWriter().write(new Date().toLocaleString());
//      response.setHeader("Refresh", "1");

        //隔3s跳轉到主頁
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("恭喜您註冊成功,3秒後回到主頁...");
        response.setHeader("Refresh", "3;url=/Day04/index.jsp");
    }

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

設定響應頭Refresh為一個數值,指定多少秒後重新整理當前頁面。
設定響應頭Refresh為 3;url=/Day05/index.jsp,指定多少秒後重新整理到哪個頁面。
可以用來實現註冊後“註冊成功,3秒後跳轉到主頁”的功能。

另外,在HTML可以利用<meta http-equiv= "" content="">標籤模擬響應頭的功能。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
      <meta http-equiv="Refresh" content="3;url=/Day04/index.jsp">
  </head>

  <body>
    恭喜您註冊成功,3秒後回到主頁.... <br>
  </body>
</html>

利用response控制是否快取資源

不快取資源:
控制瀏覽器不要快取(如驗證碼圖片不快取),設定expires為0或-1,設定Cache-Control為no-cache,Pragma為no-cache

package me.zipstream.response;

import java.io.IOException;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class NoCacheServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setIntHeader("Expires", -1);
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("當前時間是: " + new Date().toLocaleString());
    }

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

}

快取資源:
即使不明確指定瀏覽器也會快取資源,這種快取沒有截至日期。當在位址列重新輸入地址時會用快取,但是當重新整理或重新開瀏覽器訪問時會重新獲得資源。
如果明確指定快取時間,瀏覽器快取時會有一個截至日期,在截至日期到期之前,當在位址列重新輸入地址或重新開瀏覽器訪問時都會用快取,而當重新整理時會重新獲得資源。

package me.zipstream.response;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
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 CacheServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setDateHeader("Expires", System.currentTimeMillis() + 1000l*3600*24*30);
        //注意這裡時間的設定。後面不要都是int型的,至少有一個為long型。

        InputStream in = new FileInputStream(this.getServletContext().getRealPath("1.jpg"));
        OutputStream out = response.getOutputStream();

        byte[] buf = new byte[1024];
        int len = 0;

        while ((len=in.read(buf)) != -1){
            out.write(buf, 0, len);
        }

        in.close();
    }

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

利用response實現請求重定向

package me.zipstream.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 RedirectServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
//      response.setStatus(302);
//      response.setHeader("Location", "/Day04/index.jsp");

        response.sendRedirect("/Day04/index.jsp");
    }

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

}

古老方法:
response.setStatus(302);
response.addHeader("Location","URL");

快捷方式:
response.sendRedirect("URL");