其餘更多java基礎文章:
java基礎學習(目錄)html
Servlet是一個特殊的Java類, 是運行在 Web 服務器中的小型 Java 程序(即:服務器端的小應用程序)。servlet 一般經過 HTTP(超文本傳輸協議)接收和響應來自 Web 客戶端的請求。這個Java類必須繼承HttpServlet。每一個Servlet能夠響應客戶端的請求,Servlet提供不一樣的方法用於響應客戶端請求,例如doGet,doPost,doPut等java
Tomcat 是Web應用服務器,是一個Servlet/JSP容器. Tomcat 做爲Servlet容器,負責處理客戶請求,把請求傳送給Servlet,並將Servlet的響應傳送回給客戶.而Servlet是一種運行在支持Java語言的服務器上的組件.。web
Servlet最多見的用途是擴展Java Web服務器功能,提供很是安全的,可移植的,易於使用的CGI替代品。 從http協議中的請求和響應能夠得知,瀏覽器發出的請求是一個請求文本,而瀏覽器接收到的也應該是一個響應文本。 spring
Java Servlet API 是Servlet容器(tomcat)和servlet之間的接口,它定義了serlvet的各類方法,還定義了Servlet容器傳送給Servlet的對象類,其中最重要的就是ServletRequest和ServletResponse。因此說咱們在編寫servlet時,須要實現Servlet接口,按照其規範進行操做。瀏覽器
在瀏覽器的地址欄輸入:http://ip:port/appNames/servlet緩存
1)經過瀏覽器和ip:port和這個服務器創建鏈接。
2) 瀏覽器會生成一個請求數據包(路徑appNames/servlet)向服務器發送請求。
3) 服務器收到請求數據包,分析請求資源路徑作精準定位,經過請求的appName查找webapps文件下面的appName作匹配,匹配上了須要獲取web.xml中的servlet(mapping)。
4) 服務器建立兩個對象:
第一個對象:請求對象,該對象實現了HttpServletRequest接口,服務器會將請求數據包中的數據解析出來,存儲在該對象裏。這樣作的好處是沒有必要理解http協議,只須要讀取request。
第二個對象:響應對象,實現了HttpServletResponse接口,做用是servlet處理完成後的結果能夠存放到該對象上,而後服務器依據該對象的數據生成響應數據包。
5) servlet在執行servlet()方法時,能夠經過request獲取請求數據,也能夠將處理結果存放到response上。而後服務器與響應對象直接造成一個默契,生成一個響應數據包給瀏覽器。
6)瀏覽器解析服務器返回的響應數據包,生成響應的結果。tomcat
Servlet訪問的過程:
Http請求---->web.xml--------> url -pattern----->servlet-name----->servlet-class-----> QuickStratServlet(對應的Class文件)安全
Servlet生命週期可分爲5個步驟springboot
簡單總結:只要訪問Servlet,service()就會被調用。init()只有第一次訪問Servlet的時候纔會被調用。 destroy()只有在Tomcat關閉的時候纔會被調用。bash
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
}
}
複製代碼
@SpringBootApplication
public class ServletApp {
@Bean
public ServletRegistrationBean MyServlet(){
return new ServletRegistrationBean(new MyServlet(),"/myserv/*");
}
public static void main(String[] args){
SpringApplication.run(ServletApp.class, args);
}
}
複製代碼
#Servlet細節
當一個請求發送到servlet容器的時候,容器先會將請求的url減去當前應用上下文的路徑做爲servlet的映射url,好比我訪問的是http://localhost/hiway/user/aaa.html,個人應用上下文是hiway,容器會將http://localhost/hiway去掉,剩下的/user/aaa.html部分拿來作servlet的映射匹配。這個映射匹配過程是有順序的,並且當有一個servlet匹配成功之後,就不會去理會剩下的servlet了。其匹配規則和順序以下:
在Servlet規範中,對於Servlet單例與多例定義以下:
「Deployment Descriptor」, controls how the servlet container provides instances of the servlet.For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the servlet container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.
上面規範提到: 若是一個Servlet沒有被部署在分佈式的環境中,通常web.xml中聲明的一個Servlet只對應一個實例。 而若是一個Servlet實現了SingleThreadModel接口,就會被初始化多個實例。默認20個
因此我的理解Servlet不算單例,只是容器讓它只實例化一次,變現出來的是單例的效果而已
對上面的三種方法進行測試,能夠代表用它們都能設計出線程安全的Servlet程序。可是,若是一個Servlet實現了SingleThreadModel接口,Servlet引擎將爲每一個新的請求建立一個單獨的Servlet實例,這將引發大量的系統開銷。SingleThreadModel在Servlet2.4中已再也不提倡使用;一樣若是在程序中使用同步來保護要使用的共享的數據,也會使系統的性能大大降低。這是由於被同步的代碼塊在同一時刻只能有一個線程執行它,使得其同時處理客戶請求的吞吐量下降,並且不少客戶處於阻塞狀態。另外爲保證主存內容和線程的工做內存中的數據的一致性,要頻繁地刷新緩存,這也會大大地影響系統的性能。因此在實際的開發中也應避免或最小化 Servlet 中的同步代碼;**在Serlet中避免使用實例變量是保證Servlet線程安全的最佳選擇。**從Java 內存模型也能夠知道,方法中的臨時變量是在棧上分配空間,並且每一個線程都有本身私有的棧空間,因此它們不會影響線程的安全
在servlet的配置當中,
<load-on-startup>1</load-on-startup>
複製代碼
的含義是:
標記容器是否在啓動的時候就加載這個servlet。當值爲0或者大於0時,表示容器在應用啓動時就加載這個servlet;當是一個負數時或者沒有指定時,則指示容器在該servlet被選擇時才加載。正數的值越小,啓動該servlet的優先級越高。
配置load-on-startup後,servlet在startup後當即加載,但只是調用servlet的init()方法,用以初始化該servlet相關的資源。初始化成功後,該servlet可響應web請求;如未配置load-on-startup,容器通常在第一次響應web請求時,會先檢測該servlet是否初始化,如未初始化,則調用servlet的init()先初始化,初始化成功後,再響應請求。
能夠將url-pattern 配置一個/,表明該servlet是缺省的servlet。什麼是缺省的servlet? 當你訪問資源地址全部的servlet都不匹配時,缺省的servlet賦值處理。其實,web應用中全部的資源的響應都是servlet負責,包括靜態資源(html頁面)。(有配置缺省的servlet,沒法訪問到靜態資源。)