1. 程式人生 > >JavaWeb學習四(HttpServletResponse和HttpServletRequest)

JavaWeb學習四(HttpServletResponse和HttpServletRequest)

一.伺服器處理請求流程

1.請求響應流程圖

這裡寫圖片描述

  • 伺服器每次收到請求時,都會為這個請求開闢一個新的執行緒
  • 伺服器會把客戶端的請求資料封裝到request物件中
  • request就是請求資料的載體!(筷子)
  • 伺服器還會建立response物件,這個物件與客戶端連線在一起
  • 它可以用來向客戶端傳送響應(手機)

二.HttpServletResponse

  • ServletResponse–> 與協議無關的型別
  • HttpServletResponse –>與Http協議相關的型別

1.狀態碼

  • sendError(int sc) –>傳送錯誤狀態碼,例如404 500
  • sendError(int sc,String msg) –>傳送錯誤狀態碼,還可以帶一個錯誤資訊
  • setStatus(int sc)–> 傳送成功的狀態碼 可以用來發送302
public class CServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          response.sendError(404,"成都東軟校園網無法訪問"
); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }

訪問此Servlet效果如下圖:

這裡寫圖片描述

2.響應頭

Content-Type Refresh Location等等

  • 頭就是一個鍵值對,可能會存在一個頭(一個名稱 一個值),也可能會存在一個頭(一個名稱 多個值)

  • setHeader(String name,String value):適用於單值的響應頭

public
class DServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("aaa","AA"); response.setStatus(200); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }

這裡寫圖片描述

  • addHeader(String name,String value):使用於多值的響應頭
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               response.addHeader("aaa","AAA");
               response.addHeader("aaa", "AA");
               response.addHeader("aaa", "A");
               response.setStatus(200);
    }


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

    }

}

這裡寫圖片描述

  • setIntHeader(String name,int value):適用於單值的int型別的響應頭
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               response.setIntHeader("aaa",1);
               response.setStatus(200);
    }


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

    }

}

這裡寫圖片描述

  • addIntHeader(String name,int value):適用於多值的int型別的響應頭
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               response.addIntHeader("aaa",1);
               response.addIntHeader("aaa",22);
               response.addIntHeader("aaa",333);
               response.setStatus(200);
    }


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

    }

}

這裡寫圖片描述

  • setDateHeader(String name,long value):適用於單值的毫秒型別的響應頭
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               response.setDateHeader("expires",60*60*24*1000);//快取24小時
               response.setStatus(200);
    }


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

    }

}

這裡寫圖片描述

不過注意一般在開發的時候會這麼設定,快取大多自然不好

response.setDateHeader("expires",-1);//設定過期時間為-1 
  • addDateHeader(String name,long value):適用於多值的毫秒型別的響應頭
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               response.addDateHeader("expires",60*60*24*1000);//快取24小時
               response.addDateHeader("expires",60*60*24*10000);//快取240小時
               response.setStatus(200);
    }


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

    }

}

這裡寫圖片描述

3.案例

(1).傳送302,設定Location頭,完成重定向
public class DServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               System.out.println("DServlet...");
               response.setHeader("Location","/javaweb2/EServlet");
               response.setStatus(302);
    }


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

    }

}
public class EServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           System.out.println("EServlet...");
    }

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

    }

}

訪問DServlet,控制檯打印出

DServlet...
EServlet...

這裡寫圖片描述

大致圖解

這裡寫圖片描述

(2).定時重新整理,設定Refresh頭,你可以把它理解成,定時的重定向
public class DServlet extends HttpServlet {


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

              response.setContentType("text/html;charset=utf-8");

              PrintWriter printWriter=response.getWriter();

              printWriter.println("您好,5秒鐘將進入重定向");

              response.setHeader("Refresh","5;URL=/javaweb2/EServlet");
    }


}
public class EServlet extends HttpServlet {

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

           response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("你看到不是亂碼!");
    }

}

這裡寫圖片描述

(3).禁止瀏覽器快取
public class FServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              response.setHeader("Cache-Control","no-cache");
              response.setHeader("pragma","no-cache");
              response.setDateHeader("expires",-1);
              response.getWriter().print("hello world");
    }

}

注意:<meta>標籤可以代替響應頭

<meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
<meta http-equiv="Content-Type" content="Cache-Control"; charset="no-cache">
...

4.響應體

響應體通常是html,也可以是圖片
response的兩個流

  • ServletOutputStream 用來向客戶端傳送位元組資料
ServletOutputStream out=response.getOutputStream();
  • PrintWriter: 用來向客戶端傳送字元資料 需要設定編碼
PrintWriter writer=response.getWriter();
public class GServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              String ss="hello world";
              byte[] bys=ss.getBytes();
              response.getOutputStream().write(bys);

              String path="‪E:/F/黑黑.jpg";
              FileInputStream fis=new FileInputStream(path);
              byte[] byss=IOUtils.toByteArray(fis);//將圖片轉換成位元組陣列
              response.getOutputStream().write(byss);
    }


}

注意兩個流不能同時使用

5.直接進行重定向

public class DServlet extends HttpServlet {


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

        System.out.println("DServlet...");
              response.sendRedirect("/javaweb2/EServlet");//直接進行重定向的方法
    }


}
public class EServlet extends HttpServlet {

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

          System.out.println("EServlet...");
    }



}

控制檯列印

DServlet...
EServlet...

三.HttpServletRequest(封裝了客戶端所有的請求資料)

1.請求協議

  • 請求行
  • 請求頭
  • 空行
  • 請求體(GET提交方式是沒有請求體的)

2.常用方法

(1).獲取常用資訊
A.獲取客戶端ip
request.getRemoteAddr();
B.獲取請求方式
request.getMethod();//可能是POST 也可能是GET
(2).獲取HTTP請求頭
String getHeader(String name);//適用於單值頭
 int getIntHeader(Stirng name);//適用於單值int型別的請求頭
long getDateHeader(String name);//適用於單值毫秒型別的請求頭
Enumeration <String> getHeaders(String name);//適用於多值請求頭

舉例

public class AServlet extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String addr=request.getRemoteAddr();
        String method=request.getMethod();
        String userAgent=request.getHeader("user-Agent");

        System.out.println("addr:"+addr);
        System.out.println("請求方式:"+method);
        System.out.println("user-Agent:"+userAgent);
    }



}

列印

addr:0:0:0:0:0:0:0:1
請求方式:GET
user-Agent:Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko

user-Agent包括了很多資訊,訪問資源瀏覽器的資訊,系統資訊等

(3).獲取請求URL
  • String getScheme():獲取協議 http
  • String getServerName():獲取伺服器名 localhost
  • String getServerPort():獲取伺服器埠 8080
  • String getContextPath():獲取專案名
  • String getServletPath():獲取Servlet路徑
  • String getQueryString():獲取引數部分 即問號後面的部分
  • String getRequestURI():獲取請求URI
  • StringBuffer getRequestURL():獲取請求URL

這裡寫圖片描述

舉例

public class BServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           String http=request.getScheme();
           String ServerName=request.getServerName();
           int Serverport=request.getServerPort();
           String ContextPath=request.getContextPath();
           String ServletPath=request.getServletPath();
           String QueryString=request.getQueryString();
           String uri=request.getRequestURI();
          StringBuffer url=request.getRequestURL();

          System.out.println("協議名:"+http);
          System.out.println("伺服器名:"+ServerName);
          System.out.println("伺服器埠:"+Serverport);
          System.out.println("專案名:"+ContextPath);
          System.out.println("servlet的路徑:"+ServletPath);
          System.out.println("引數:"+QueryString);
          System.out.println("uri:"+uri);
          System.out.println("url:"+url.toString());

    }



}

列印

協議名:http
伺服器名:localhost
伺服器埠:8080
專案名:/javaweb3
servlet的路徑:/BServlet
引數:null     //因為你是get請求所以沒有引數
uri:/javaweb3/BServlet
url:http://localhost:8080/javaweb3/BServlet
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
         <form action="/javaweb3/BServlet" method="get">
                <input type="text" name="text"><br/>
                <input type="submit" value="提交">           
         </form>
</body>
</html>

列印

協議名:http
伺服器名:localhost
伺服器埠:8080
專案名:/javaweb3
servlet的路徑:/BServlet
引數:text=1444
uri:/javaweb3/BServlet
url:http://localhost:8080/javaweb3/BServlet
(4).防盜鏈

如果請求不是通過本站的超連結發出的,傳送錯誤狀態碼404,Referer,這個請求頭表示請求的來源!

public class CServlet extends HttpServlet {


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

        String Referer=request.getHeader("Referer");
        System.out.println(Referer);
        if(Referer==null||Referer.contains("localhost")) {//直接訪問Referer值是null
                response.sendRedirect(request.getContextPath()+"/DServlet");
        }else {
               response.sendError(404, "滾開");
        }

    }
}
(5).獲取請求引數

請求引數是由客戶端傳送給伺服器的 有可能是在請求體中(POST)

  • String getParameter(String name):獲取指定名稱的請求引數值,適用於單值請求引數
  • String [] getParameterValues(String name):獲取指定名稱的請求引數值,適用於多值請求引數
  • Enumeration<String> getParameterNames():獲取所有請求引數名稱
  • Map<String,String[]> getParameterMap():獲取所有請求引數,其中Key為引數名,value為引數值
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
        <form action="/javaweb3/EServlet">
        使用者名稱:<input type="text" name="username"><br/>
    密碼:<input type="password" name="password"><br/>
   性別:<input type="radio" name="sex" value="nan"><input type="radio" name="sex" value="nv"><br/>
  愛好:<input type="checkbox" name="love" value="ppq">乒乓球
  <input type="checkbox" name="love" value="lq">籃球
  <input type="checkbox" name="love" value="ymq">羽毛球<br/>
  <input type="submit" value="提交">


        </form>
</body>
</html>
public class EServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
              String username=request.getParameter("username");
              String password=request.getParameter("password");

              System.out.println("username:"+username);
              System.out.println("password:"+password);

              String [] loves=request.getParameterValues("love");
              for(String s:loves) {
                  System.out.println("love:"+s);
              }

              Enumeration<String> enumeration=request.getParameterNames();

              while(enumeration.hasMoreElements()) {
                  System.out.println(enumeration.nextElement());
              }

              Map<String,String[]> map=request.getParameterMap();

              for(String name:map.keySet()) {
                  String [] values=map.get(name);
                  System.out.println(name+":"+Arrays.toString(values));
              }
    }

}

列印

username:123
password:123
love:ppq
love:lq
love:ymq
username
password
sex
love
username:[123]
password:[123]
sex:[nan]
love:[ppq, lq, ymq]
(6).請求轉發和請求包含

RequestDispatcher rd=request.getRequestDispatcher("/MyServlet") 使用request獲取RequestDispatcher物件,方法的引數是被轉發或包含的Servlet路徑

A.請求轉發

public class OneServlet extends HttpServlet {

       @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("OneServlet...");
        resp.setHeader("aaa","AAA");//設定響應頭

        resp.getWriter().print("aaaaaaa");//設定響應體

        req.getRequestDispatcher("/TwoServlet").forward(req, resp);

    }
}
public class TwoServlet extends HttpServlet {

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

        System.out.println("TwoServlet...");
        response.getWriter().print("bbbbbb");//設定響應體

    }

}

這裡寫圖片描述

總結

由下一個Servlet完成響應體,當前Servlet可以設定響應頭(留頭不留體)

如果把OneServlet改成如下

public class OneServlet extends HttpServlet {

       @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("OneServlet...");
        resp.setHeader("aaa","AAA");

        for(int i=0;i<1024*24+1;i++) {
            resp.getWriter().print("a");
        }
        //相當於呼叫了TwoServlet的service的方法
        req.getRequestDispatcher("/TwoServlet").forward(req, resp);

    }
}

為什麼打印出了?不是留頭不留體嘛?
這裡寫圖片描述
看吧!控制檯還是報錯了的!
這裡寫圖片描述
總結
在請求轉發的時候,最好不要做過多的操作,過多的操作情況下,就好別使用轉發

B.請求轉發
public class OneServlets extends HttpServlet {


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

        System.out.println("OneServlets...");
           response.setHeader("aaa","AAA");

           response.getWriter().print("OneServlet one!!!");

           request.getRequestDispatcher("/TwoServlets").include(request, response);

    }


}
public class TwoServlets extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("TwoServlets...");

           response.getWriter().print("TwoServlet two!!!");
    }


}

這裡寫圖片描述

總結

由兩個Servlet共同未完成響應體(都留)

無論是請求轉發還是請求包含,都在一個請求範圍內,使用同一個request和response!

(7).request域

Servlet中三大域物件: request session application

  • void setAttribute(String name,Object value)
  • object getAttribute(String name)
  • void removeAttribute(String name)

這裡寫圖片描述

同一請求範圍內使用request.setAttribute(),request.getAttribute()來傳值

(8).請求轉發和重定向的區別
  • 請求轉發是一個請求一次響應,而後者是兩次請求兩次響應
  • 請求轉發位址列不變化,而後者顯示後一個請求的地址
  • 請求轉發只能轉發到本專案其他Servlet,而後者不只能重定向到本專案的其他Servlet,還能定向到其他專案
  • 請求轉發是伺服器端行為,只需給出轉發的Servlet路徑,而後者需要給出requestURI ,即包含專案名
  • 請求轉發和重定向效率,轉發高 ,因為是一個請求
  • 需要位址列發生變化,那麼必須重定向
  • 需要在下一個Servlet中獲取request域中的資料,必須要使用轉發

END!!!!!!!!