JavaEE復習計劃
對於這一塊,也只是用到了 Web 開發的相關技術,並且很多技術已經過時或者被民間更好的取代,所以側重於最基礎的 Servlet API、會話機制。
Servlet API
頂級接口:Servlet、ServletConfig、ServletContext
最常用的類:HttpServlet
Servlet 接口
廣義上說,一個類實現了 Servlet 接口那麽就稱這個類是 Servlet,也就是說 該接口中定義了所有 servlet 都必須實現的方法 。
方法一覽:
- init(ServletConfig)
- service(ServletRequest, ServletResponse)
- destroy()
- getServletConfig()
- getServletInfo()
根據官方 API 的解釋,簡單翻譯過來就是這麽個意思:
Servlet 是一個運行在服務器端的小的 JAVA 程序,Servlet 接受和響應來自客戶端的請求(通常是 HTTP協議);
為了實現該接口,可以繼承 javax.servlet.GenericServlet
也可以繼承 javax.servlet.http.HttpServlet
.
該接口定義了初始化、處理請求、刪除 Servlet 的方法,這些方法被稱作生命周期方法,以如下的順序調用:
- Servlet 被構造,調用
init()
方法初始化 - 所有請求交給
service
- 處理完畢之後使用
destroy
方法銷毀資源,等待 GC 回收
除了生命周期方法之外該接口還提供了一個 getServletConfig 方法,Servlet 獲得一些啟動信息。
ServletConfig接口
ServletConfig 的對象是由容器構造的。
初始化 Servlet 的時候,該對象傳遞一些啟動的參數給 Servlet (以 init() 方法參數的形式)
可以簡單理解:ServletConfig 中封裝了 web.xml 中給 Servlet 配置的參數 ( <init-param>
)
方法一覽:
- getInitParameter(String name)
- getInitParameterNames()
- getServletContext()
- getServletName()
Servlet 和 ServletConfig 是一一對應的,一個 Servlet 都跟著一個 config 對象
ServletContext接口
Servlet 上下文封裝了與 Servlet 所在容器通信的一些方法。
對此其實應該很熟悉,是我們常用的四大存儲域之一,是範圍最大的一塊。
ServletContext 與容器對應的;一個 ServletContext 可以對應多個 Servlet.
其中定義了很多常用的方法,比如獲取絕對路徑的 getRealpath,存儲數據的 get/set Attrbiute.
獲得 ServletContext 的集中方式:
- ServletConfig.getServletContext();
- HttpSession.getServletContext();
- FilterConfig.getServletContext();
- ServletContextEvent.getServletContext();
PS:既然 ServletConfig 可以拿到,那麽它的實現類也都是可以的~
GenerciServlet抽象類
它實現了之前說的 Servlet 和 ServletConfig 接口,但是畢竟是個抽象類,只有一個方法未實現,所以上面有八個方法都可以使用,此外還有他自己的一些方法。
下面說說重要的幾個:
init(ServletConfig)
默認的實現可以總結為兩句:{this.config = config;init();}
,可以看出此類肯定有個 ServletConfig 類型的屬性,在 init 中進行保存 config 的引用方便後續方法的使用。
然後直接又調用了一個空參的 init 方法,這個方法就是 GenerciServlet 自己定義的,默認空實現,如果有自己的初始化邏輯,重寫這個空參方法即可,並且不需要再調用super.init(config)
方法。abstract service(ServletRequest, ServletResponse)
是的,唯一的一個抽象方法,唯一的一個未實現的。
服務器收到請求會調用 service 進行處理,怎麽處理也應該由開發者去實現,註意參數為 ServletRequest,一般我們需要強轉成 HttpServletRequest ,一般也就是處理 Http 請求吧。
然後還有兩個打印日誌的方法,這就是全部的方法了。
HttpServlet類
它繼承自 GenericServlet ,並實現了它未實現的 service 方法,從名字可以看出是專門處理 Http 請求的,開發者寫的 Servlet 一般也是繼承自這個類。
然後它實現的方法做了兩件事:
- 將 ServletRequest/ServletResponse 強轉為 HttpServletRequest/HttpServletResponse
- 調用自己定義的 service(HttpServletRequest, HttpServletResponse) 方法(此方法是 protected 的)
那麽,它自己定義的這個 service 方法到底幹了什麽呢?
簡單說就是通過 request.getMethod()
獲取到請求方式,然後根據這個請求方式來分別調用 doXXX 方法,所以開發者一般都會重寫其 doGet 和 doPost。
PS:protected 修飾的方法可以覆蓋,但是權限不能變小。
API 總結
從實現者、調用者、構造者的角度來看就是:
API名字 | 實現者 | 調用者 | 構造者(new) |
---|---|---|---|
Servlet | 開發者 | 容器 | 容器 |
ServletConfig | 容器 | 開發者 | 容器 |
ServletContext | 容器 | 開發者 | 容器 |
Request | 容器 | 開發者 | 容器 |
Response | 容器 | 開發者 | 容器 |
RequestDispatcher | 容器 | 開發者 | 容器 |
Cookie | 容器 | 開發者 | 開發者 |
HttpSession | 容器 | 開發者 | 容器 |
Filter | 開發者 | 容器 | 容器 |
Listener | 開發者 | 容器 | 容器 |
一個請求的流程
服務器以 Tomcat 為例,那麽一個請求的過程大概可以分為下面幾步:
服務器啟動階段
Tomcat 啟動時檢測自身配置文件 conf 目錄,如果配置有問題,則無法啟動。
Tomcat 檢查 webapps 下工程的所有的 web.xml 文件,如果該文件有問題,則 tomcat 報錯,啟動正常(報錯的工程無法訪問,其他工程可以正常使用)。瀏覽器地址欄輸入地址,回車
瀏覽器將地址信息打包成標準的 HTTP 請求字符串
如果輸入的是域名,那麽進行 DNS 解析,然後通過網絡發送到服務器地址
服務器接受到請求並解析,將請求信息打包到 HttpServletRequest/response 對象中
到
web.xml
中尋找指定的url-pattern
,根據 servlet-name 找到 Servlet-class容器檢測內存中是否有該 Servlet 的對象,如果有則使用原來的對象,如果沒有則使用反射構造 Servlet 對象
【沒有找到對象】容器調用 init() --> 方法初始化
容器調用 service(ServletRequest) --> doXx
我們重寫 DOXxx 方法 完成業務邏輯
容器將 response 對象轉換成標準的 HTTP 響應字符串,再通過網絡回送給瀏覽器
瀏覽器接受標準的響應信息,解析,顯示
當然上面的每一步其實還可以細分,但是這裏就先不分的過於細了。
JavaEE復習計劃