剛開始接觸servlet的時候,其實不是太理解servlet的,後來通過慢慢摸爬滾打式的的學習,有了一點本身的理解。java
servlet的產生還要從Java和HTTP提及
- Java的servletAPI是可以讓Java更好地支持web應用。HTTP協議是無狀態的(也就是瀏覽器的每個請求都會被服務器看成是接收到的惟一請求處理,當用戶再次發出請求時,服務器並不知道是同一個用戶),而servletAPI提供了會話機制(session),能夠關聯同一用戶的請求;同時,HTTP協議是基於文本的,也就是在一個HTTP請求中,全部的數據都是以文本的形式表示。而Java又是強類型語言,用Java去處理必然會將這些數據一一對應到Java的數據類型中,過程十分繁瑣。servletAPI將HTTP公開給Java平臺,意味着開發人員能夠直接根據通訊要求更加直觀地編寫HTTP服務器代碼。
- servletAPI的核心對象:request、response、servlet。servlet是一個單例的對象,servlet的用途是接收請求,處理以後返回響應;request對象封裝了各類請求細節(表單、字符串參數);response對象包含了響應首部、生成響應文本的輸出流等。
- servlet容器。servlet容器內能夠包含多個web應用,一個web應用裏能夠包含多個servlet,(在早期的servlet規範中,servlet的映射地址是寫在web.xml中,在servlet3.0以後就用java註解映射地址) 當客戶端發出請求,首先會被web容器處理,而在servlet規範中,servlet容器一般監聽8080端口上的全部請求(如tomcat),當請求發出後,容器會解析命名空間對應到web應用中,再對應到web應用中的servlet的URL。
servlet生命週期
在每一個web中實例化一次,生命週期是由web容器決定的,在Servlet的整個生命週期內,init()方法只被調用一次,web容器建立一個Servlet實例而且調用Servlet的init()方法進行初始化,當容器關閉時,調用destroy()方法釋放資源。web
servlet中的線程安全問題
每個jsp文件最後都會編譯成servlet,而後按照其生命週期執行。servlet實質仍是一個Java類,最終編譯成CLASS文件。當客戶端發起一個請求,服務端把jsp文件編譯成CLASS文件,而且建立一個該類的實例,(因爲servlet是單例的,該實例在整個jvm中只有一份)而後建立一個線程去處理這個請求, 當客戶端有多個用戶同時發起請求,服務端則會建立多個線程去處理,每一個客戶端對應一個線程。瀏覽器
- servlet中的實例變量: 實例變量是在堆中分配的,並被屬於該實例的全部線程共享,因此不是線程安全的。
- 內置對象中的OUT,REQUEST,RESPONSE,SESSION,CONFIG,PAGE,PAGECONXT是線程安全的(由於每一個線程對應的request,respone對象都是不同的,不存在共享問題), APPLICATION在整個系統內被使用,因此不是線程安全的。
- 局部變量: 局部變量在堆棧中分配,由於每一個線程都有它本身的堆棧空間,因此是線程安全的.。
- 靜態類: 靜態類不用被實例化,就可直接使用,也不是線程安全。
servlet容器如何同時處理多個請求
Servlet採用多線程來處理多個請求同時訪問。servlet依賴於一個線程池來服務請求。線程池其實是一系列的工做者線程集合。Servlet使用一個調度線程來管理工做者線程。當容器收到一個Servlet請求,調度線程從線程池中選出一個線程,將請求傳遞給該線程,而後由該線程來執行Servlet的service方法。當這個線程正在執行的時候,容器收到另一個請求,調度線程一樣從線程池中選出另外一個線程來服務新的請求,容器並不關心這個請求是否訪問的是同一個Servlet.當容器同時收到對同一個Servlet的多個請求的時候,那麼這個Servlet的service()方法將在多線程中併發執行。Servlet容器默認採用單實例多線程的方式來處理請求,這樣減小產生Servlet實例的開銷,提高了對請求的響應時間,對於Tomcat能夠在server.xml中經過<Connector>元素設置線程池中線程的數目。tomcat