1. 程式人生 > 其它 >HttpServlet中的 request & response

HttpServlet中的 request & response

1. HTTP

1. 什麼是HTTP

(超文字傳輸協議)是一個簡單的請求-響應協議,它通常執行在TCP之上

  • 文字:html,字串,…
  • 超文字:圖片,音樂,視訊,定位,地圖.……
  • 埠:80
  • Https:安全的

1.2 兩個時代

  1. http1.0
  • HTTP/1.0:客戶端可以與web伺服器連線後,只能獲得一個web資源,斷開連線
  1. http2.0
  • HTTP/1.1:客戶端可以與web伺服器連線後,可以獲得多個web資源。

1.3 Http請求

客戶端–->發請求(Request)–->伺服器

百度的請求:

Request URL:https://www.baidu.com/   請求地址
Request Method:GET    get方法/post方法
Status Code:200 OK    狀態碼:200
Remote(遠端) Address:14.215.177.39:443

Accept:text/html  
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9    語言
Cache-Control:max-age=0
Connection:keep-alive

1.3.1 請求行

請求方式:Get,Post,HEAD,DELETE,PUT,TRACT.…

  • get:請求能夠攜帶的引數比較少,大小有限制,會在瀏覽器的URL位址列顯示資料內容,不安全,但高效

  • post:請求能夠攜帶的引數沒有限制,大小沒有限制,不會在瀏覽器的URL位址列顯示資料內容,安全,但不高效。

1.3.2 訊息頭

Accept:告訴瀏覽器,它所支援的資料型別
Accept-Encoding:支援哪種編碼格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告訴瀏覽器,它的語言環境
Cache-Control:快取控制
Connection:告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機..../.

1.4 Http響應

伺服器-->響應-->客戶端

百度的響應:

Cache-Control:private    快取控制
Connection:Keep-Alive    連線
Content-Encoding:gzip    編碼
Content-Type:text/html   型別  

1.4.1 響應體

Accept:告訴瀏覽器,它所支援的資料型別
Accept-Encoding:支援哪種編碼格式  GBK   UTF-8   GB2312  ISO8859-1
Accept-Language:告訴瀏覽器,它的語言環境
Cache-Control:快取控制
Connection:告訴瀏覽器,請求完成是斷開還是保持連線
HOST:主機..../.
Refresh:告訴客戶端,多久重新整理一次;
Location:讓網頁重新定位;

1.4.2 響應狀態碼(重點)

200:請求響應成功200
3xx:請求重定向·重定向:你重新到我給你新位置去;
4xx:找不到資源404·資源不存在;
5xx:伺服器程式碼錯誤 500 502:閘道器錯誤

1.5 面試題(重點)

  • 當你的瀏覽器中位址列輸入地址並回車的一瞬間到頁面能夠展示回來,經歷了什麼?

  • 請你談談網站是如何進行訪問的!

  1. 輸入一個域名;回車

  2. 檢查本機的 C:\Windows\System32\drivers\etc\hosts配置檔案下有沒有這個域名對映;
    2.1 有:直接返回對應的ip地址,這個地址中,有我們需要訪問的web程式,可以直接訪問
    2.2沒有:去DNS伺服器找,找到的話就返回,找不到就返回找不到;

1.6 HTTP一篇就夠了,很詳細

2. ServletContext

一個web容器啟動時,會為建立一個對應的ServletContext物件,它代表了當前web應用;

2.1 共享資料 getServletContext()

我們在一個Servlet中通過servlerContext物件儲存(set)的資料,可以在另一個servlet通過servlerContext物件get到

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //this.getInitParameter();	獲取初始化引數
        //this.getServletConfig();	獲取Servlet配置
        //this.getServletContext();	獲取Servlet上下文
        ServletContext servletContext = this.getServletContext();
        String username = "admin";
        servletContext.setAttribute("username",username);//將一個數據儲存到了ServletContext中 
        //void setAttribute(String var1, Object var2);
    }
}
public class GetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        String username = (String)context.getAttribute("username");

        //設定響應格式,否則中文預設GBK格式在瀏覽器上顯示會亂碼
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        
        resp.getWriter().print("名字"+username);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

2.2 獲取初始化引數 getInitParameter

  • 在web.xml中配置一些web應用初始化引數
    <!--配置一些web應用初始化引數-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>
  • doGet中獲取url
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	ServletContext context = this.getServletContext();
    	String url = context.getInitParameter("url");
    	resp.getWriter().print(url);
	}

2.3 請求轉發 getRequestDispatcher

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext context = this.getServletContext();
        System.out.println("進入了sd4");
        RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp");//轉發的請求路徑
        requestDispatcher.forward(req,resp);//呼叫forward實現請求轉發
        //合併寫  context.getRequestDispatcher("/gp").forward(req,resp);
    }

2.4 讀取資原始檔

  • 在resources目錄下新建db.properties
username=root
password=123456
  • 思路:需要一個檔案流 + Properties類
public class ServletDemo05 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/kuang/servlet/aa.properties");

        Properties prop = new Properties();
        prop.load(is);
        String user = prop.getProperty("username");
        String pwd = prop.getProperty("password");

        resp.getWriter().print(user+":"+pwd);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3. HttpServletResponse

web伺服器接收到客戶端的http請求,針對這個請求,分別建立一個代表請求的HttpServletRequest物件,代表響應的一個HttpServletResponse;

  • 如果要獲取客戶端請求過來的引數:找HttpServletRequest

  • 如果要給客戶端響應一些資訊:找HttpServletResponse

3.1 下載檔案

思路

要獲取下載檔案的路徑
下載的檔名是啥?
設定想辦法讓瀏覽器能夠支援下載我們需要的東西
獲取下載檔案的輸入流
建立緩衝區
獲取OutputStream物件
將FileOutputStream流寫入到buffer緩衝區
使用OutputStream將緩衝區中的資料輸出到客戶端!
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 1. 要獲取下載檔案的路徑
    String realPath = "F:\\班級管理\\西開【19525】\\2、程式碼\\JavaWeb\\javaweb-02-servlet\\response\\target\\classes\\秦疆.png";
    System.out.println("下載檔案的路徑:"+realPath);
    // 2. 下載的檔名是啥?
    String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);
    // 3. 設定想辦法讓瀏覽器能夠支援(Content-Disposition)下載我們需要的東西,中文檔名URLEncoder.encode編碼,否則有可能亂碼
    resp.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"UTF-8"));
    // 4. 獲取下載檔案的輸入流
    FileInputStream in = new FileInputStream(realPath);
    // 5. 建立緩衝區
    int len = 0;
    byte[] buffer = new byte[1024];
    // 6. 獲取OutputStream物件
    ServletOutputStream out = resp.getOutputStream();
    // 7. 將FileOutputStream流寫入到buffer緩衝區,使用OutputStream將緩衝區中的資料輸出到客戶端!
    while ((len=in.read(buffer))>0){
        out.write(buffer,0,len);
    }

    in.close();
    out.close();
}

3.2 驗證碼功能

  • 前端實現
  • 後端實現,需要用到 Java 的圖片類,生產一個圖片
public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //如何讓瀏覽器3秒自動重新整理一次;
        resp.setHeader("refresh","3");
        
        //在記憶體中建立一個圖片
        BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
        //得到圖片
        Graphics2D g = (Graphics2D) image.getGraphics(); //筆
        //設定圖片的背景顏色
        g.setColor(Color.white);
        g.fillRect(0,0,80,20);
        //給圖片寫資料
        g.setColor(Color.BLUE);
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,20);

        //告訴瀏覽器,這個請求用圖片的方式開啟
        resp.setContentType("image/jpeg");
        //網站存在快取,不讓瀏覽器快取
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");

        //把圖片寫給瀏覽器
        ImageIO.write(image,"jpg", resp.getOutputStream());
    }

    //生成隨機數
    private String makeNum(){
        Random random = new Random();
        String num = random.nextInt(9999999) + "";
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 7-num.length() ; i++) {
            sb.append("0");
        }
        num = sb.toString() + num;
        return num;
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

3.3 實現重定向

一個web資源(B)收到客戶端A請求後,B他會通知A客戶端去訪問另外一個web資源C,這個過程叫重定向

常見場景:使用者登入

引數為:專案名/地址名

resp.sendRedirect("/ServletHttpResponse/getImage");

<%--action:這裡提交的路徑,需要尋找到專案的路徑--%>
<%--${pageContext.request.contextPath}代表當前的專案--%>
<form action="${pageContext.request.contextPath}/redirect" method="get">
    username <input name="username" type="text"> <br>
    password: <input name="password" type="password"> <br>
    <input type="submit">
</form>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    System.out.println(username +":  "+password);
    //引數為:專案名/地址名
    resp.sendRedirect("/ServletHttpResponse/success.jsp");
    }

4. HttpServletRequest

HttpServletRequest代表客戶端的請求,使用者通過Http協議訪問伺服器,HTTP請求中的所有資訊會被封裝到HttpServletRequest,通過這個HttpServletRequest的方法,獲得客戶端的所有資訊;

常用兩個方法

request獲取請求的資料,並請求轉發

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    req.setCharacterEncoding("utf-8");
    resp.setCharacterEncoding("utf-8");

    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobbys = req.getParameterValues("hobbys");
    System.out.println("=============================");
    //後臺接收中文亂碼問題
    System.out.println(username);
    System.out.println(password);
    System.out.println(Arrays.toString(hobbys));
    System.out.println("=============================");


    System.out.println(req.getContextPath());
    //通過請求轉發
    //這裡的 / 代表當前的web應用
    req.getRequestDispatcher("/success.jsp").forward(req,resp);
}
<div>
    <form action="${pageContext.request.contextPath}/login" method="post">
        使用者名稱:<input type="text" name="username"> <br>
        密碼: <input type="password" name="password"> <br>
        愛好:
        <input type="checkbox" name="hobby" value="coding">程式設計
        <input type="checkbox" name="hobby" value="game">遊戲
        <input type="checkbox" name="hobby" value="film">看電影
        <input type="checkbox" name="hobby" value="running">跑步
        <br>
        <input type="submit">
    </form>
</div>

5. 面試題:請你聊聊重定向和轉發的區別?

  1. 相同點: 頁面都會實現跳轉

  2. 不同點

  • 請求轉發的時候,url不會產生變化 狀態碼:307
  • 重定向時候,url位址列會發生變化 狀態碼:302