1. 程式人生 > >Servlet第三篇(response;request)

Servlet第三篇(response;request)

進制 自動 創建 stat fileinput setfont mage return 數值

Tomcat收到客戶端的http請求,會針對每一次請求,分別創建一個代表請求的request對象、和代表響應的response對象
  那麽我們獲取瀏覽器提交過來的數據,找request對象即可。response對象代表http響應,那麽我們向瀏覽器輸出數據,找response對象即可。

response對象

什麽是HttpServletResponse對象?

  http響應由狀態行、實體內容、消息頭、一個空行組成。HttpServletResponse對象就封裝了http響應的信息。

HttpServletResponse的應用

輸出utf-8中文字符

  1. getOutputStream().write(xxx.getBytes())

    調用getOutputStream()方法向瀏覽器輸出數據
        print
          Tomcat使用IOS 8859-1編碼對其進行轉換,“中國”根本對ISO 8859-1編碼不支持。
        write
          "你好呀我是中國".getBytes()這句代碼在轉成byte[]數組的時候默認查的是gb2312編碼,而"你好呀我是中國"支持gb2312編碼,所以可以正常顯示出來。

  • 設置頭信息,告訴瀏覽器我回送的數據編碼是utf-8的
 response.setHeader("Content-Type", "text/html;charset=UTF-8");
  • 使用meta標簽模擬http消息頭,告訴瀏覽器回送數據的編碼和格式
servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
  1. getwrite().write(xxx)
  • 使用getWriter()顯示中文數據,只需要一個方法就搞掂了!

      response.setContentType("text/html;charset=UTF-8")(設置中文碼表和瀏覽器)把response.setCharacterEncoding("UTF-8")(設置中文碼表)的工作也做了

    調用getWriter()方法向瀏覽器輸出數據
      對於getWriter()方法而言,是Writer的子類,那麽只能向瀏覽器輸出字符數據,不能輸出二進制數據


實現文件下載

  java的文件上傳下載都是通過io流來完成的,既然要下載圖片,首先要能夠讀取到它   

   //獲取到資源的路徑
    String path = this.getServletContext().getRealPath("/download/1.png");
    //讀取資源
    FileInputStream fileInputStream = new FileInputStream(path);
    //獲取到文件名,路徑在電腦上保存是\\形式的。
    String fileName = path.substring(path.lastIndexOf("\\") + 1);

  告訴瀏覽器,我要下載這個文件  

    //設置消息頭,告訴瀏覽器,我要下載1.png這個圖片
    response.setHeader("Content-Disposition", "attachment; filename="+fileName);
    為了解決文件名亂碼,我們要進行URL編碼,代碼如下:
    response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

    將讀取到的內容回送給瀏覽器

    //把讀取到的資源寫給瀏覽器
    int len = 0;
    byte[] bytes = new byte[1024];
    ServletOutputStream servletOutputStream = response.getOutputStream();

      while ((len = fileInputStream.read(bytes)) > 0) {
      servletOutputStream.write(bytes, 0, len);
      }

      //關閉資源
      servletOutputStream.close();
      fileInputStream.close();

實現自動刷新
讓瀏覽器實現自動刷新,那肯定又是修改消息頭了。  

  //每3秒自動刷新網頁一次
  response.setHeader("Refresh", "3");

設置緩存 

瀏覽器本身就存在著緩存機制

禁止緩存的功能

 //瀏覽器有三消息頭設置緩存,為了兼容性!將三個消息頭都設置了
  response.setDateHeader("Expires", -1);
  response.setHeader("Cache-Control","no-cache");
  response.setHeader("Pragma", "no-cache");

實現數據壓縮
  GZIPOutputStream寫數據的時候,是把數據寫到ByteArrayOutputStream上的,等會還要把數據取出來,再寫給瀏覽器

  //告訴瀏覽器這是gzip壓縮的數據
  response.setHeader("Content-Encoding","gzip");

  生出隨機圖片
  要生成一張圖片,java提供了BufferedImage類供我們使用

   //在內存中生成一張圖片,寬為80,高為20,類型是RGB
    BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

    //獲取到這張圖片
    Graphics graphics = bufferedImage.getGraphics();

    //往圖片設置顏色和字體
    graphics.setColor(Color.BLUE);
    graphics.setFont(new Font(null, Font.BOLD, 20));

    //往圖片上寫數據,先寫個12345,橫坐標是0,縱坐標是20【高度】
    graphics.drawString("12345", 0, 20);

    把圖片寫給瀏覽器,java又提供了圖片流【ImageIO】給我們使用

    //把圖片傳進去,類型是jpg,寫給瀏覽器
    ImageIO.write(bufferedImage, "jpg", response.getOutputStream());

重定向跳轉

    //重定向到index.jsp頁面
  response.sendRedirect("/zhongfucheng/index.jsp");

  其實sendRedirect()方法就是對setStatus(302)和setHeader()進行封裝,原理就是setStatus()和setHeader()
 getWriter和getOutputStream細節
  getWriter()和getOutputStream()兩個方法不能同時調用。如果同時調用就會出現異常
  Servlet程序向ServletOutputStream或PrintWriter對象中寫入的數據將被Servlet引擎從response裏面獲取,Servlet引擎將這些數據當作響應消息的正文,然後再與響應狀態行和各響應頭組合後輸出到客戶端。
  Servlet的serice()方法結束後【也就是doPost()或者doGet()結束後】,Servlet引擎將檢查getWriter或getOutputStream方法返回的輸出流對象是否已經調用過close方法,如果沒有,Servlet引擎將調用close方法關閉該輸出流對象.

request對象

什麽是HttpServletRequest

  HttpServletRequest對象代表客戶端的請求,當客戶端通過HTTP協議訪問服務器時,HTTP請求頭中的所有信息都封裝在這個對象中,開發人員通過這個對象的方法,可以獲得客戶這些信息。

HttpServletRequest常用方法

 獲得客戶機【瀏覽器】信息
  getRequestURL方法返回客戶端發出請求時的完整URL。
  getRequestURI方法返回請求行中的資源名部分。
  getQueryString 方法返回請求行中的參數部分。
  getPathInfo方法返回請求URL中的額外路徑信息。額外路徑信息是請求URL中的位於Servlet的路徑之後和查詢參數之前的內容,它以“/”開頭。
  getRemoteAddr方法返回發出請求的客戶機的IP地址
  getRemoteHost方法返回發出請求的客戶機的完整主機名
  getRemotePort方法返回客戶機所使用的網絡端口號
  getLocalAddr方法返回WEB服務器的IP地址。
  getLocalName方法返回WEB服務器的主機名
 獲得客戶機請求頭
  getHeader方法
  getHeaders方法
  getHeaderNames方法
 獲得客戶機請求參數(客戶端提交的數據)
  getParameter方法
  getParameterValues(String name)方法
  getParameterNames方法
  getParameterMap方法

HttpServletRequest應用

  防盜鏈
    獲取Referer這個消息頭,判斷Referer是不是從我的首頁來的。如果不是從我的首頁來的,跳轉回我的首頁。

String referer=request.getHeader("Referer");
if(referer== null||!referer.contains("http://localhost:8088/firstServlet/NewSvlt")){
response.sendRedirect("/firstServlet/NewSvlt");
return;

  表單提交數據【通過post方式提交數據】

    request.getParameter()
    request.getParameterValues()
  get方式提交數據
    通過超鏈接將數據帶給瀏覽器
      使用超鏈接將數據帶給瀏覽器

    sendRedirect()
      sendRedirect("servlet的地址?參數名="+參數值&"參數名=" +參數值);

  中文亂碼問題
    首先我們來看一下post方法是怎麽進行參數傳遞的。當我們點擊提交按鈕的時候,數據封裝進了Form Data中,http請求中把實體主體帶過去了【傳輸的數據稱之為實體主體】,既然request對象封裝了http請求,所以request對象可以解析到發送過來的數據,於是只要把編碼設置成UTF-8就可以解決亂碼問題了。

    而get方式不同,它的數據是從消息行帶過去的,沒有封裝到request對象裏面,所以使用request設置編碼是無效的。
    Tomcat默認的編碼是ISO 8859-1,那麽get方式由消息體帶過去給瀏覽器的時候肯定是用ISO 8859-1編碼了

  •     手工轉換

  技術分享圖片

  •     設置Tomcat

        在8080端口的Connector上加入 URIEncoding="utf-8",設置Tomcat的訪問該端口時的編碼為utf-8,從而解決亂碼,這種改法是固定使用UTF-8編碼的

      當然也有另一種改服務器編碼的方式。設置Tomcat的訪問該端口時的編碼為頁面的編碼 useBodyEncodingForURI="true",這種改法是隨著頁面的編碼而變。

  實現轉發
    request的getRequestDispatcher.forward(request,response)實現轉發

    (RequestDispatcher還有另外一個方法include(),該方法可以實現包含一般網頁的頭部和尾部是不需要改變的。如果我們多個地方使用Servlet輸出網頭和網尾的話,需要把代碼重新寫一遍。而使用RequestDispatcher的include()方法就可以實現包含網頭和網尾的效果了。)

    request也可以稱之為域對象,只不過ServletContext的域是整個web應用,而request的域僅僅代表一次http請求  請求轉發的細節    如果在調用forward方法之前,在Servlet程序中寫入的部分內容已經被真正地傳送到了客戶端,forward方法將拋出IllegalStateException異常。 也就是說:不要在轉發之前寫數據給瀏覽器    如果在調用forward方法之前向Servlet引擎的緩沖區中寫入了內容,只要寫入到緩沖區中的內容還沒有被真正輸出到客戶端,forward方法就可以被正常執行,原來寫入到輸出緩沖區中的內容將被清空,但是,已寫入到HttpServletResponse對象中的響應頭字段信息保持有效。

  轉發和重定向的區別
   實際發生位置不同,地址欄不同
    轉發是發生在服務器的
    轉發是由服務器進行跳轉的,細心的朋友會發現,在轉發的時候,瀏覽器的地址欄是沒有發生變化的,在我訪問Servlet111的時候,即使跳轉到了Servlet222的頁面,瀏覽器的地址還是Servlet111的。也就是說瀏覽器是不知道該跳轉的動作,轉發是對瀏覽器透明的。通過上面的轉發時序圖我們也可以發現,實現轉發只是一次的http請求,一次轉發中request和response對象都是同一個。這也解釋了,為什麽可以使用request作為域對象進行Servlet之間的通訊。
    重定向是發生在瀏覽器的
    重定向是由瀏覽器進行跳轉的,進行重定向跳轉的時候,瀏覽器的地址會發生變化的。曾經介紹過:實現重定向的原理是由response的狀態碼和Location頭組合而實現的。這是由瀏覽器進行的頁面跳轉實現重定向會發出兩個http請求,request域對象是無效的,因為它不是同一個request對象
   用法不同
    給服務器用的直接從資源名開始寫(轉發),給瀏覽器用的要把應用名寫上(重定向)
   能夠去往的URL的範圍不一樣
    轉發是服務器跳轉只能去往當前web應用的資源
    重定向是服務器跳轉,可以去往任何的資源
   傳遞數據的類型不同
    轉發的request對象可以傳遞各種類型的數據,包括對象
    重定向只能傳遞字符串
   跳轉的時間不同
    轉發時:執行到跳轉語句時就會立刻跳轉
    重定向:整個頁面執行完之後才執行跳轉

  轉發和重定向使用哪一個?
    轉發是帶著轉發前的請求的參數的。重定向是新的請求。
    典型的應用場景:
      轉發: 訪問 Servlet 處理業務邏輯,然後 forward 到 jsp 顯示處理結果,瀏覽器裏 URL 不變
      重定向: 提交表單,處理成功後 redirect 到另一個 jsp,防止表單重復提交,瀏覽器裏 URL 變了

Servlet第三篇(response;request)