HttpServletRespnse 物件 相關基本應用

凌丹妙藥發表於2020-09-01

HttpServletRespnse 物件相關基本應用

向瀏覽器輸出資料

getOutputStream()

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      resp.setHeader("Content-Type","text/html;charset=UTF-8");
      resp.getOutputStream().write("你好,aaaa".getBytes("UTF-8"));
    }

或者

getWriter()

        //設定訊息頭,設定編碼,自動重新整理時間
        resp.setHeader("Refresh","5");
        resp.setHeader("Content-Type","text/html;charset=UTF-8");
        //顯示時間
        resp.getWriter().write("實時時間是"+System.currentTimeMillis());
        /*登入後3秒跳轉可用此方法實現*/

注意事項

  1. getWriter()和getOutputStream()兩個⽅法不能同時調⽤。如果同時調⽤就會出現異常。
  2. Servlet程式向ServletOutputStream或PrintWriter物件中寫⼊的資料將被Servlet引擎從response⾥⾯獲取,Servlet引擎將這些資料當作響應訊息的正⽂,然後再與響應狀態⾏和各響應頭組合後輸出到客戶端。
  3. Servlet的serice()⽅法結束後【也就是doPost()或者doGet()結束後】,Servlet引擎將檢查getWriter或getOutputStream⽅法返回的輸出流物件是否已經調⽤過close⽅法,如果沒有,Servlet引擎將調⽤close⽅法關閉該輸出流物件。

實現檔案下載

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws  IOException {
        //獲取資源路徑
        String realPath = this.getServletContext().getRealPath("/download/二維碼.jpg");
        //讀取資源
        FileInputStream fileInputStream = new FileInputStream(realPath);
        //獲取檔名
        String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);

        //設定訊息頭,告知瀏覽器,需要下載該檔案
        resp.setHeader("Content-Disposition","attachment;filename="
                        +URLEncoder.encode(filename,"UTF-8")   //設定編碼,解決亂碼問題
                        );

//        將讀取到的內容返回給瀏覽器
        //按位元組讀取檔案,輸出流按位元組輸出檔案
        ServletOutputStream outputStream = resp.getOutputStream();

        byte[] bytes =new byte[fileInputStream.available()];  //獲取檔案位元組大小並設定
        int len = 0;
        while(  ( len = fileInputStream.read(bytes)) > 0){
            outputStream.write(bytes , 0 , len);
        }
        //關閉流
        outputStream.close();
        fileInputStream.close();
    }

注意事項:

  1. windows系統獲取檔案的路徑分隔符為 “ \\” 。

  2. 中文檔名需要加上設定編碼,否則會出想下載到的檔名亂碼。

  3. 注意最後要關閉流。

  4. 獲取檔案大小(位元組)通過 FileInputStream 的 available() 方法獲得。

    以下是通過Debug 下驗證獲取的檔案大小與檔案本身大小是否一致。

image-20200901161642779

image-20200901161610482

設定快取

 //首先要明確哪些頁面需要快取。
    //還是通過設定訊息頭,設定快取。
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //設定不快取
        /*resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma", "no-cache");
        resp.setDateHeader("Expires",-1);*/
        //設定快取,快取一分鐘
        resp.setDateHeader("Expires",System.currentTimeMillis() + 1000 * 60);
        resp.setHeader("Cache-Control","max-age");
        //輸出增加時間便於觀察
        /*配置訊息頭和訊息編碼,即可解決瀏覽器端亂碼*/
        resp.setHeader("Content-Type","text/html;charset=UTF-8");
        resp.getWriter().print("你好,aaaaa");
    }

通過除錯模式可以檢視到快取的期限。

image-20200901161342645

實現資料壓縮

 @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //壓縮資料
        String ss = "fsdfhsdfhuisdhfusdhfuids" +
                "fsdfdsfsdfsdfdsfdafdsfhsdjfhsdjkfhkjds" +
                "fdsfjdslkfjsldkfjsdlkfjsdkfsdjkff" +
                "fsjdfjdsklfjdsklfjkldsfjlksdjflksdjflkds" +
                "dsjfklsdjflsdjfkldsfkjsdkfjsldkfjsdlfk" +
                "fdsjlkfjdslkfjsdlkfjlkasjflk";
        //獲取GZIP類
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
        //輸出資料
        gzipOutputStream.write(ss.getBytes());
        //GZIPOutputStream有快取,關閉流清理快取
        gzipOutputStream.close();
        //將壓縮的資料取出來
        byte[] bytes = byteArrayOutputStream.toByteArray();
      //  resp.getWriter().write(ss+"</br>"+"</br>"+"</br>");
        System.out.println("原來的長度:    "+ss.getBytes().length);
        System.out.println("壓縮後的長度:    "+bytes.length);
        //設定編碼
        resp.setHeader("Content-Encoding","gzip");
        //把資料寫到瀏覽器,讓瀏覽器獲取到壓縮的資料
        resp.getOutputStream().write(bytes);

    }

注意: 回到前面提到的 getWriter() 和 getOutputStream() 不能同時使用。

image-20200901203711440

生出隨機圖片

@Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //通過java提供的 BufferedImage 生成一張圖片
        BufferedImage image = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
        //獲取這張圖片
        Graphics graphics = image.getGraphics();
        //設定圖片內容,顏色
        graphics.setColor(Color.white);
        graphics.setFont(new Font(null,Font.BOLD,20));
        //隨機數字使用自定義方法
        graphics.drawString(this.getNum(),0,20);
      //  graphics.fillRect(0,0,80,20);   不需要填充
        //告知瀏覽器,傳送的是一張圖片
        resp.setHeader("ContentType","jpeg");
        //Java提供圖⽚流給我們使⽤,這是⼀個⼯具類傳送圖片
        ImageIO.write(image,"jpeg",resp.getOutputStream());
    }

    private String getNum() {   //自定義生成隨機數字方法
        Random random = new Random();
        int nextInt = random.nextInt(9999999);
        String num = String.valueOf(nextInt);

        StringBuilder stringBuffer =new StringBuilder();
        //不夠數字就填充
        for (int i =0 ;7- num.length() > i ;i++){
            stringBuffer.append("0");
        }
        return stringBuffer.append(num).toString();
    }

注意 :是否要使用Graphics . fillRect() 方法填充, 填充是否會覆蓋要顯示的內容,這需要使用者自己衡量決定使用哪一種。

image-20200901224550868

重定向跳轉

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //重定向
        resp.sendRedirect("/hello.jsp");
    }

image-20200901224848505

注意: jsp 頁面是否放在正確的路徑上。

image-20200901224936330

web.xml 配置檔案

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>demoServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.demoServlet</servlet-class>
  </servlet>
  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>demoHttpServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.demoHttpServlet</servlet-class>
  </servlet>
  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>downloadServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.downloadServlet</servlet-class>
  </servlet>
  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>dataServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.dataServlet</servlet-class>
    <init-param>

      <param-name>fileEncoding</param-name>

      <param-value>UTF-8</param-value>

    </init-param>
  </servlet>
  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>cachedServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.cachedServlet</servlet-class>
  </servlet>
  <servlet>
    <!--為這個Servlet去一個名字,一般是和類名一致-->
    <servlet-name>graphServlet</servlet-name>
    <!--Servlet的位置,有包名需要加上包名-->
    <servlet-class>com.ling.graphServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>graphServlet</servlet-name>
    <url-pattern>/graphServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>demoHttpServlet</servlet-name>
    <url-pattern>/demoHttpServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>demoServlet</servlet-name>
    <url-pattern>/demoServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>downloadServlet</servlet-name>
    <url-pattern>/downloadServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>cachedServlet</servlet-name>
    <url-pattern>/cachedServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <!--配置對映路徑-->
    <servlet-name>dataServlet</servlet-name>
    <url-pattern>/dataServlet</url-pattern>
  </servlet-mapping>
</web-app>

注意: 需要設定編碼時,要明確編碼型別。

相關文章