多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > Servlet的歷史與規范

Servlet的歷史與規范

來源:程序員人生   發布時間:2016-06-13 11:11:56 閱讀次數:2683次

1、Servlet歷史

1. Servlet的由來

  • 背景
    上世紀90年代,隨著Internet和閱讀器的飛速發展,基于閱讀器的B/S模式隨之火爆發展起來。
    最初,用戶使用閱讀器向WEB服務器發送的要求都是要求靜態的資源,比如html、css等。
    但是可以想象:根據用戶要求的不同動態的處理并返回資源是天經地義必須的要求。

  • CGI
    必須要滿足上述需求,所以CGI(Common Gateway Interface)出現了。CGI程序使用C、Shell Script或Perl編寫,CGI是為特定操作系統編寫的(如UNIX或Windows),不可移植,CGI程序對每一個要求產生新的進程去處理。步驟以下:

    1. WEB服務器接收1個用戶要求;
    2. WEB服務器將要求轉交給CGI程序處理;
    3. CGI程序將處理結果返回給WEB服務器
    4. WEB服務器把結果送回用戶;
      這里寫圖片描述
  • Java
    與此同時,Java語言也在迅速發展。必定的,Java要支持上述需求。
    Java有兩種方案來實現動態需求,它們都屬于JavaEE技術的1部份。

    1. applet
      這是純客戶端(閱讀器)方案,applet就是閱讀器中的Java插件,閱讀器通過它就可以夠解釋履行WEB服務器發過來的Java代碼,從而實現動態。但是,明顯這類方案不好,既需要閱讀器必須安裝插件,又受限于閱讀器,所以Java代碼不能太多和太復雜。

      比如,如果安裝了JRE,雖然IE閱讀器會自動啟用Java插件,但是你可以輕易制止。再比如Chrome還需要你手動去安裝插件才行,普通用戶連Java是甚么都不知道他怎樣會去裝呢?
      IE以下圖:

      這里寫圖片描述

    2. Servlet
      既然閱讀器不方便履行Java代碼,那自然還是服務端來履行了,所以Servlet出現了,Servlet就是server真個applet的意思。

2. Servlet的工作原理

其實Servlet的工作原理基本類似上面的CGI,不過Servlet比CGI更好。

  1. WEB服務器接收1個用戶要求;

  2. WEB服務器將要求轉交給WEB服務器關聯的Servlet容器;

  3. Servlet容器找到對應的Servlet并履行這個Servlet;

  4. Servlet容器將處理結果返回給WEB服務器;

  5. WEB服務器把結果送回用戶;

3. Servlet的發展

  1. Servlet誕生后,SUN公司很快發現了Servlet編程非常繁瑣,這是由于:

    • Servlet代碼中有大量冗余代碼,每一個Servlet都有1模1樣的或基本近似的代碼,比如out輸出你可能就得寫成百遍;
    • 開發Servlet必須精通網頁前端和美工,你得非常不直觀的在Servlet中寫前端代碼,這使得實現各種頁面效果和風格非常困難。
  2. 所以,SUN鑒戒了Microsoft的ASP,正式提出JSP(Servlet1.1),已期望能代替Servlet。但是很快,SUN發現JSP也有問題:

    • 前端開發人員需要看JSP中大量的令他困惑的后端代碼;
    • 一樣,Servlet開發人員也得在復雜的前端代碼中找到其能寫Servlet代碼的地方;
  3. 所以,Servlet1.2出現了,這個版本的Servlet提倡了MVC思想:

    • JSP(V):將后端代碼封裝在標簽中,使用大量的標簽,JSP只用來寫前端代碼而不要有后臺代碼;
    • Servlet(C):Servlet完成Controller的功能再加上部份代碼邏輯;
    • Model(M):Servlet將數據發送給Model,Model包括部份代碼邏輯,最主要的Model也代表著被組織好的用于返回的數據。終究,Model數據會被顯示在JSP上(V)。

基本上到這里Servlet的大方向已固定了,隨之,成熟的發展至今 - 2016年5月26日…


↑以上,是關于Servlet的歷史部份。↓下面來說1講Servlet規范中重要知識點。


聲明:以下內容歸納自官方Servlet規范和JavaEE規范等文檔。

2、Servlet規范

下載地址
Servlet規范官方地址:JSR 340: Java Servlet 3.1 Specification(中文版網上有人翻譯了,可以自己搜索找找)
可以自己下載瀏覽,終究版final是2013年5月28發布的Servlet3.1。

1. Servlet概述

Servlet有兩種意思:

  1. 廣義上是:基于Java技術的Web組件,被容器托管,用于生成動態內容。

    再詳細點說,Servlet是JavaEE組件中的 -> Web組件的 -> 1種。
    (其它兩種是JavaServer Faces和JavaServer Page)

  2. 狹義上說:是JavaEE API中的1個interface,javax.servlet.Servlet

Servlet 容器/引擎:

  1. Servlet容器也能夠叫引擎,Container/Engine,用于履行Servlet。

  2. 容器是以內嵌附加組件的情勢存在于Web服務器或利用服務器中的。

  3. 容器本身(不依賴Web服務器)就提供了基于要求/響應發送模型的網絡服務,解碼基于MIME的要求,格式化基于MIME的響應。

  4. 所有容器必須實現HTTP協議的要求/響應模型。其它協議不強求,如HTTPS。




下面開始說1下規范的核心要點。
請注意:我不是要完全的論述Servlet規范,畢竟你可以直接看規范。這里我只是要記錄我認為重要的點。

為了方便描寫,先聲明1些名詞:

  • web.xml = 部署描寫符(Deployment Descriptor )
  • 容器 = Servlet Container/Engine



2. Servlet Interface

Servlet生命周期:

Servlet的生命(周期)是由容器管理的,換句話說,Servlet程序員不能用代碼控制其生命。

  1. 加載和實例化:
    時機取決于web.xml的定義,如果有<load-on-startup>x</load-on-startup>則在容器啟動時,反之則在第1次針對這個Servlet的要求產生時。

  2. 初始化:
    實例化后會立馬進行初始化。也就是履行init方法。

  3. 要求處理:
    初始化后,Servlet就能夠接受要求了。

    • 基本方式是履行Servlet接口中的service方法。

    • 固然,API也提供了HttpServlet抽象類,其中有doGet、doPost等特殊方法。

    • 注意:任意的容器依照規范必須實現上述幾種方法,所以你的代碼寫在這幾個方法中都可以。

  4. 終止服務:

    1. 容器會在適合的時候燒毀某個Servlet對象,這個策略取決于容器的開發者/商。

    2. 在容器關閉的時候Servlet對象1定會被燒毀。

    3. 當1或2產生時,也就是Servlet對象被燒毀時,destroy方法會被調用。

3. Request

1. 要求路徑元素

  1. Context Path
    '/'開頭,但不以'/'結尾

  2. Servlet Path
    '/'開頭

  3. PathInfo
    要末為null要末以'/'開頭

    例如:
    這里寫圖片描述
    這里寫圖片描述

2. 要求編碼

  1. 要求會以甚么編碼情勢送給服務器端呢?

    HTTP協議沒有強迫規定,所以實際上這是由閱讀器自己決定的,決定后閱讀器可以通過entity-body中的Content-Type項告知服務器自己使用了甚么編碼。但是!大部份情況下閱讀器不會這么做的。比如說,Get要求是沒有entity-body的,自然也不會使用Content-Type了。

  2. 在服務端,我們Servlet規范 規定了如果要求沒有指定編碼的話,容器必須使用IOS⑻859⑴來解碼。為了讓開發人員知道要求給沒給出編碼,容器會在沒給的情況下通過getCharacterEncoding 返回null來告知我們。

  3. 為了在我們明知道不是ISO⑻859⑴編碼的情況下給我們自主權,ServletRequest提供了setCharacterEncoding(String enc);

4. Servlet Context

1個Web利用對應1個ServletContext接口的實例。

1. 獲得資源:
ServletContext接口提供了直接訪問Web利用中靜態內容(意思是說你獲得jsp返回就是jsp源碼)層次結構的文件的方法。

  • getResource

  • getResourceAsStream

    這兩個方法需要的String參數必須是以'/'開頭的,這個'/'代表相對:

    • ServletContextPath的路徑。

    • WEB-INF/lib中的jar中的METE-INF/resources路徑。

5. Response

代表容器的響應,沒有特別需要注意的。

6. Filtering

過濾器,是Java中1種代碼重用技術,通過攔截要求改變HTTP要求的內容、響應、Header信息。

其它沒甚么好說的,只需要注意的1點是:

  • 匹配的Filter極可能是多個而不是1個,所以Filter是1個FilterChain設計。

    所有FilterdoFilter方法終究都需要調用chain.doFilter(request, response);方法來觸發調用鏈的下1個Filter或如果是最后1個Filter那末直接訪問目標資源。

7. 映照要求到Servlet的規則

  1. 用于映照到Servlet的路徑是:

    • 客戶端要求的URL - ServletContext上下文路徑 - 路徑參數。

    • 例如當客戶端要求的URL是:http://www.google.com/testproject/action/servlet1?param1=asd時,那末需要映照的路徑是:/action/servlet1

  2. 重要!重要!重要!選擇映照到的Servlet的規則是,依照以下的順序查找,如果已選定1個就會匹配成功不會繼續往下:

    1. 先精確匹配<url-pattern>,成功則選擇。(精確匹配

    2. 遞歸遍歷路徑樹,選擇最長的路徑匹配。(最長匹配

    3. 如果URL最后1個部份包括擴大名,比如/action/servlet1.jsp,容器將選擇專門聲明了要處理此擴大名要求的Servlet。(擴大名匹配

    4. 如果123都沒有匹配,容器將提供1個后備方案,1般來講是提供1個"default" Servlet。(低保匹配,優先級最低,提供1個最低保障)

  3. 映照規范

    1. '/'字符開始,以'/*'字符結束的字符串:用于路徑匹配。(這是1個準確嚴謹的定義而已)。

    2. '*.'開始的字符串用于擴大名映照。

    3. 空字符串""是特殊的URL,精確映照到利用的上下文根,即http://host:port/<context-root>/,這類情況("")相當于<url-pattern>/<url-pattern>。

    4. 只包括'/'字符的字符串表示利用的"default" Servlet。

  4. 隱式映照
    容器可以為1些擴大名定義1些影射映照,比如來1個.jsp的,那末如果上面的顯示映照沒有攔截.jsp,此時這里應當發揮作用。

  5. tomcat中是怎樣做的(我看了Jetty也是差不多)

    1. tomcat在其頂級的web.xml中定義了且開放了2個<servlet>(這么說是由于其實不只2個,不過那幾個是注釋狀態)

      <servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> ... <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> ... <load-on-startup>3</load-on-startup> </servlet> <!-- default servlet mapping --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The mappings for the JSP servlet --> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>

      可以看到tomcat踐行了如上所述的Servlet規范。

    2. jsp:org.apache.jasper.servlet.JspServlet這個Servlet終究會:

      • 先將.jsp文件變成java文件(即1個Servlet);
      • 然后再compile.class;
    3. default:org.apache.catalina.servlets.DefaultServlet這個Servlet終究會:

      • 為所有無被匹配到的URL做匹配,即”低?!逼ヅ?;
      • 如果找到相應的資源了就返回,沒有找到或產生1些異常就返回400/404等狀態碼及其頁面,長相以下:
        這里寫圖片描述

8. Session

  1. 會話跟蹤機制

    HTTP協議是無狀態的,但是記錄狀態,也就是說記錄來自同1客戶真個要求的需求是必須的。所以人們發明了會話跟蹤機制。

    Servlet規范定義了1個簡單的HttpSession接口,允許容器使用幾種方法來實現會話跟蹤,從而使得Web利用開發人員沒必要來關心和寫這塊的代碼。(容器只能幫我們實現單機會話跟蹤,散布式利用多機狀態下,我們需要自己寫代碼實現Session同步)。

  2. 幾種方法

    1. Cookies
      是最經常使用的機制,且所有Servlet容器必須支持。容器有能力(但是需要程序員顯式調用)向客戶端發送1個cookie,用來記錄會話,標準名字必須是JSESSIONID

    2. URL重寫
      比如:http://www.sss.com/aa/bb.html;jessionid=1234
      要注意,使用的是分號';',這個叫路徑參數,區分于查詢參數。

  3. 如何使用Session跟蹤機制

    1. 需要程序員手動調用

      //a. 有session返回,沒有新生成1個 request.getSession(); request.getSession(true); //b. 有session返回,沒有返回null request.getSession(false);
    2. 如果使用的a方式,再加上使用cookie機制的情況下,容器的第1次響應(Response)會向客戶端寫1個JSESSIONID,客戶端從第2次要求(Request)開始會帶著JSESSIONID,以下圖:

      這里寫圖片描述

      這里寫圖片描述

9. Web Application

1. WEB-INF目錄:
此目錄是1個特殊目錄,不能由容器直接提供給客戶端訪問。可以通過:

  1. 調用ServletContextgetResourcegetResourceAsStream來訪問。

  2. 還可以通過RequestDispatcher來調用從而公然這些內容。

2. WEB-INF目錄的內容:

  1. /WEB-INF/web.xml部署描寫文件。

  2. Servlet和其它類的目錄/WEB-INF/classes/

  3. Java歸檔文件(jar)區域/WEB-INF/lib/*.jar

10. Application Lifecycle Events - 利用生命周期事件

Servlet API為ServletContext、HttpSession、ServletRequest這3個對象添加了事件。這可讓Servlet開發人員更好的控制上述3個對象生命周期。

  1. ServletContext

    事件類型 描寫 監聽器接口
    生命周期 ServletContext剛創建并可用于服務它的第1個要求或行將關閉 javax.servlet.ServletContextListener
    更改屬性 ServletContext的屬性已添加、已刪除、已替換 javax.servlet.ServletContextAttributeListener
  2. HttpSession

    事件類型 描寫 監聽器接口
    生命周期 會話已創建、燒毀、超時 javax.servlet.http.HttpSessionListener
    更改屬性 HttpSession的屬性已添加、已刪除、已替換 javax.servlet.http.HttpSessionAttributeListener
    改變ID HttpSession的ID將被改變 javax.servlet.http.HttpSessionIdListener
    會話遷移 HttpSession已被激活或鈍化 javax.servlet.http.HttpSessionActivationListener
    對象綁定 對象已從HttpSession綁定或解綁 javax.servlet.http.HttpSeesionBindingListener
  3. ServletRequest

    事件類型 描寫 監聽器接口
    生命周期 1個要求已開始由Web組件處理 javax.servlet.ServletRequestListener
    更改屬性 已在servlet上添加、移除、替換屬性 javax.servlet.ServletRequestAttributeListner
    異步事件 超時、連接終止或完成異步操作處理 javax.servlet.AsyncListener

實例化時機:

容器必須在開始履行進入利用的第1個要求之前完成Web利用中所有監聽器類的實例化。

11. Deployment Descriptor - web.xml

1. 關于順序

  1. Servlet加載順序
    <load-on-startup>x</load-on-startup>中的x指定加載順序,必須不小于0,越小越早加載。

  2. Filter

    1. 加載順序:
      應當是沒有要求,不會依照根據web.xml中聲明的順序,但也不是隨機的,以某種規則固定,這個不重要。

    2. 過濾器鏈構造規則:
      規范中6.2.4 節,待驗證總結。

  3. Listener調用順序
    根據在web.xml中注冊的順序來被調用。例外的,生命周期中的燒毀事件觸發的destroy會被反方向的順次調用。

2. 關于初始化參數:

  1. ServletContext的初始化參數:

    1. 設值:由于1個利用只有1個ServletContext,所以是直接聲明在根<web-app>下的:

      <context-param> <param-name>contextParam1</param-name> <param-value>11context11</param-value> </context-param>
    2. 取值/設值:只要獲得到了ServletContext對象,就能夠使用其getInitParameter(String name)方法來取值,同時也能夠使用setInitParameter(String name, String value);來設值,所以很多地方都可以取值/設值。

  2. Listener的初始化參數:

    1. 設值:監聽器沒有自己獨立的初始化參數配置,想要使用的話可以借助將參數配置在ServletContext的初始化參數位置。

    2. 取值/設值:如上。

  3. Filter的初始化參數:

    1. 設值:只能在<filter>中使用<init-param>來設置值:

      <filter> <filter-name>FirstFilter</filter-name> <filter-class>filter.FirstFilter</filter-class> <init-param> <param-name>firstFilterParam1</param-name> <param-value>11filter11</param-value> </init-param> </filter>
    2. 取值:只有獲得了某1個FilterFilterConfig對象以后,才能使用此對象的方法getInitParameter(String name)方法來取值。

    3. 另外的:當你自己寫1個Filter的時候,除實現Filter接口以外,你還可以選擇學習類似GenericServlet的方式,額外的實現FilterConfig接口并覆蓋其getInitParameter(String name)方法,從而可以在自己的Filter的任何方法中都能調用取值方法而不必顯示獲得FilterConfig對象。像下面這樣:

      public class FirstFilter implements Filter, FilterConfig{ ... }
  4. Servlet的初始化參數:

    1. 設值:只能在<servlet>中使用<init-param>來設置值:

      <servlet> <servlet-name>FirstServlet</servlet-name> <servlet-class>servlet.FirstServlet</servlet-class> <init-param> <param-name>FirstServletParam1</param-name> <param-value>11FirstServlet11</param-value> </init-param> </servlet>
    2. 取值:跟Filter類似,ServletServletConfig對象,只要獲得到它就能夠使用其getInitParameter(String name)方法來取值。

    3. 另外的:通常我們不會直接實現Servlet接口而是使用繼承GenericServlet/HttpServlet的方式,那末(如我在上面Filter“另外的”部份所說)我們就能夠利用它們的實現直接使用getInitParameter(String name)方法來取值。

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 日本久久综合视频 | 亚洲欧美一级久久精品 | 亚洲美女色视频 | 色综合天天综合网国产成人网 | 一区二区视频在线观看 | 手机看片福利久久 | 另类图片小说 | 性欧美videofree另类hd | 欧美jizzjizz在线播放 | 国产日韩片| jizzjizzjizz亚洲18 | 成人免费视频视频在线不卡 | 亚洲精品一区二区三区在线播放 | 久久久久成人精品一区二区 | 亚洲网站在线免费观看 | 亚洲 欧美 日韩在线一区 | 伊人久久99亚洲精品久久频 | 一区二区三区四区无限乱码在线观看 | 亚洲成人娱乐网 | 成人午夜又粗又硬有大 | 日韩精品 欧美 | 一区二区三区四区在线视频 | 三级国产短视频在线观看 | 波多野结衣免费线在线 | 亚洲网站视频在线观看 | 最新毛片久热97免费精品视频 | 日本一区二区在线 | 欧美黑人xxxxww | 欧美一区二区三区视频 | 国产成人青草视频 | 最新中文字幕乱码在线 | 亚洲精品国产男人的天堂 | 91久久九九精品国产综合 | 欧美成人综合在线 | 久久精品国产2020 | h免费网站 | 尤物视频在线看 | 久久久国产这里有的是精品 | 亚洲第一在线视频 | 国产激情在线观看完整流畅 | 男女xx|