瀏覽器-Tomcat服務器-請求與響應


  瀏覽器訪問服務器,本質就是請求資源。
  比如請求靜態資源:index.html,我們在瀏覽器地址欄輸入:www.a.com/index.html,瀏覽器為了支持HTTP協議,發送的數據必須符合HTTP協議數據的格式,也就是這樣:

  GET /index.html HTTP/1.1
  Accept-Language:zh-cn
  Connection:Keep-Alive
  Host:www.a.com
  User-Agent:Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
  Accept-Encoding:gzip,deflate


  這些信息就成了請求信息,瀏覽器利用Socket,通過網絡IO流發往服務器。如果做個比喻的話,瀏覽器比作男生,服務器比作女生,我想表達的意思是,瀏覽器是主動鏈接,並且主動請求數據,也就是想要的資源,而服務器存在資源,她只會等待瀏覽器主動請求她,她才會做出響應。

  此時服務器必須已經開啟,因為她要監聽某一個端口才能知道有人給她發信息了,這里比如是 80 端口。服務器監聽80端口,有點類似於事件驅動編程的感覺,服務器利用ServerSocket,得到請求信息。服務器解析請求信息,得到需要請求的資源。這里先簡單一分為二:


1 請求靜態資源:

  服務器將會去服務器實現定義好的工作目錄下,也是我們網站發布打包后的文件存放的地方,尋找a.html文件,若找到使用IO流,將文件加載到內存中,設置狀態碼為200,再輸出到網絡IO流,發送給瀏覽器,瀏覽器接收到響應信息,截取響應體,使用渲染引擎(所謂的內核)進行渲染。若找不到文件,則服務器設置響應頭為404,我們可以自定義一句話來說明原因,大多數服務器返回404 File Not Found。這就是我們加載靜態文件的流程。

 

2 請求動態資源servlet:

  先說說動態語言,即運行時才能得知變量的類型。而動態資源,就是未執行的.class文件,得到瀏覽器的請求信息,服務器執行一系列的事先定義好的.class文件,得到一個動態的結果返回給瀏覽器。

  做個比喻,好比靜態資源就是你要買一輛普通的車,你就直接到車店,發送請求給車店,車店得到請求,解析它,知道你要買哪輛,然后返回給你汽車(有些痴人說夢哈)。動態資源呢,就是,你要私人定制一個豪華車,然后你就去汽車廠,發送請求給汽車廠,汽車廠得到請求之后,解析它,獲得一些有用信息:車大小,里面配置,外表裝飾等等,請注意,這里沒有現成的車直接返回,而是得通過一系列的生產車間動態生成,等到生產完成,返回定制汽車,連接關閉。

  比喻打完,開始說正常流程。服務器得到瀏覽器發來的請求信息之后,解析它,得到了要執行的類名。這里就用到了【反射】,個人感覺反射技術很偉大,雖然確實降低性能,但是降低了類與類之間的耦合,就好比動態資源,我不清楚如果沒有反射,我們將如何獲得動態資源。得到想要的類名,利用反射,得到該類的對象,執行想要的方法,然后返回結果。

 

3 Servlet繼承體系

 

4 Servlet生命周期

  生命周期方法
    init():當它第一次被創建的時候,執行該方法(只執行一次).
    service():對客戶端響應方法。
    destroy():當它被銷毀時,執行該方法。

  一個Servlet服務對應的只有一個Servlet對象,達到了“一個對象,多處服務”的效果,節約內存。用白話來解釋就是,我們所有人訪問的這個Servlet服務,使用的都是同一個Servlet對象。接下來給出Servlet對象從出生到死亡的步驟:

    1 實例化對象(使用構造方法)
    2 初始化(使用init()函數)
    3 服務(使用service()函數)
    4 銷毀(調用destroy()函數)

  網站的過程是第一個人訪問,然后很多人訪問,最后服務器關閉。

  第一個人訪問網站 更多人訪問網站 服務器關閉
調用的方法 調用上述1,2,3方法 調用上述3方法 調用上述4方法

 

  Servlet路徑

  長路徑優先,這里指,<url-pattern>內容</url-pattern>
      絕對路徑精確匹配,優先級高。例:/A/B
      路徑匹配,通配符匹配           例:/*
      擴展名匹配,優先級最低        例:*.html

      注意:匹配不能混用。


  多線程問題:因為我們操作的是同一個Servlet對象。
      如果定義全局變量,可能會出現線程安全問題。

 

  ServletConfig:只屬於這個Servlet的私有配置信息

  Servlet通過ServletConfig獲取配置信息,如下:

<servlet>
      <servlet-name>名字</servlet-name>
      <servlet-class>類的完全限定名</servlet-class>
      <init-param>
          <param-name>fruit</param-name>
          <param-value>apple</param-value>
      </init-param>
  </servlet>

  這里我們通過ServletConfig來獲得里面的配置信息,注意,這里的配置信息是私有的,只屬於這個Servlet對象。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out=response.getWriter();
        out.println("fruit:"+getInitParameter("fruit"));
        out.flush();
        out.close();
}

 

  ServletContext:屬於這個Web應用程序的所有Servlet對象的共有配置信息

  一個ServletContext對應一個應用。
  一個ServletConfig對應一個Servlet。
  目的:
    1 實現數據的共享。比如登陸時的名字,用戶的權限,和Session很類似。

      在一個Servlet類中,添加了一個全局數據,getServletContext().setAttribute("role", "manager");

      在另一個Servlet類中,就能得到此數據,getServletContext().getAttribute("role");

      2016-09-08  15:56:22   ???這里的疑問,難道ServletContext底層和Session有關???拋出疑問。。。

    2 共享web.xml信息。(必須是全局配置信息)
        配置全局<context-param></context-param>

  <context-param>
      <param-name>名字</param-name>
      <param-value>值</param-value>
  </context-param>

    3 獲取應用下任意資源的絕對路徑(硬盤。。)
        getServletContext().getRealPath("路徑");

 

 

 

  注:此文章針對Java應用服務器Tomcat,至於其它服務器的請求和響應原理,我沒做考證,所以我沒將猜測說出來。

 

 

 

                                                                                                                                                                                

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM