自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java Servlet 工作原理問答

開發(fā) 后端
本文來自stackoverflow的問答,討論了Java Servlet的工作機制,如何進行實例化、共享變量和多線程處理。

問題:Servlet是如何工作的?Servlet 如何實例化、共享變量、并進行多線程處理?

假設(shè)我有一個運行了大量 Servlet 的 web 服務(wù)器。通過 Servlet 之間傳輸信息得到 Servlet 上下文,并設(shè)置 session 變量。

現(xiàn)在,如果有兩名或更多使用者向這個服務(wù)發(fā)送請求,接下來 session 變量會發(fā)生什么變化?究竟是所有用戶都是用共同的變量?還是不同的用戶使用的變量都不一樣?如果是后者,服務(wù)器如何區(qū)分不同用戶?

另一個相似的問題,如果有 *n* 名用戶訪問一個特定的 Servlet,那么該 Servlet 是僅在***個用戶***訪問的時候?qū)嵗€是分別為每個用戶實例化?

回答(BalusC):

ServletContext

當(dāng) Servlet 容器(比如 Apache Tomcat)啟動后,會部署和加載所有 web 應(yīng)用。當(dāng)web 應(yīng)用被加載,Servlet 容器會創(chuàng)建一次 ServletContext,然后將其保存在服務(wù)器的內(nèi)存中。web 應(yīng)用的 web.xml 被解析,找到其中所有 servlet、filterListener@WebServlet、@WebFilter@WebListener 注解的內(nèi)容,創(chuàng)建一次并保存到服務(wù)器的內(nèi)存中。對于所有過濾器會立即調(diào)用 init()。當(dāng) Servlet 容器停止,將卸載所有 web 應(yīng)用,調(diào)用所有初始化的 Servlet 和過濾器的 destroy() 方法,***回收 ServletContext 和所有 Servlet、Filter 與 Listener 實例。

當(dāng)問題中的 Servlet 配置的 load-on-startup 或者 @WebServlet(loadOnStartup) 設(shè)置了一個大于 0 的值,則同樣會在啟動的時候立即調(diào)用 init() 方法。“load-on-startup”中的值表示那些 Servlet 會以相同順序初始化。如果配置的值相同,會遵循 web.xml 中指定的順序或 @WebServlet 類加載的順序。另外,如果不設(shè)置 “load-on-startup” 值,init() 方法只在***次 HTTP 請求***問題中的 Servlet 時才被調(diào)用。

HttpServletRequest 與 HttpServletResponse

Servlet 容器附加在一個 web 服務(wù)上,這個 web 服務(wù)會在某個端口號上監(jiān)聽 HTTP 請求,在開發(fā)環(huán)境中這個端口通常為 8080,生產(chǎn)環(huán)境中通常為 80。當(dāng)客戶端(web 瀏覽器)發(fā)送了一個 HTTP 請求,Servlet 容器會創(chuàng)建新的 HttpServletRequestHttpServletResponse 對象,傳遞給已創(chuàng)建好并且請求的 URL 匹配 url-patternFilterServlet 實例中的方法,所有工作都在同一個線程中處理。

request 對象可以訪問所有該 HTTP 請求中的信息,例如 request header 和 request body。response 對象為你提供需要的控制和發(fā)送 HTTP 響應(yīng)方法,例如設(shè)置 header 和 body(通常會帶有 JSP 文件中的 HTML 內(nèi)容)。提交并完成HTTP 響應(yīng)后,將回收 request 和 response 對象。

HttpSession

當(dāng)用戶***次訪問該 web 應(yīng)用時,會通過 request.getSession() ***次獲得 HttpSession。之后 Servlet 容器將會創(chuàng)建 HttpSession,生成一個唯一的 ID(可以通過 session.getId() 獲?。┎Υ嬖诜?wù)器內(nèi)存中。然后 Servlet 容器在該次 HTTP 響應(yīng)的 Set-Cookie 頭部設(shè)置一個 Cookie,以 JSESSIONID 作為 Cookie 名字,那個唯一的 session ID 作為 Cookie 的值。

按照 HTTP cookie 規(guī)則(正常 web 瀏覽器和 web 服務(wù)端必須遵循的標(biāo)準(zhǔn)),當(dāng) cookie 有效時,要求客戶端(瀏覽器)在后續(xù)請求的 Cookie 頭中返回這個 cookie。使用瀏覽器內(nèi)置的 HTTP 流量監(jiān)控器,你可以查看它們(在 Chrome、Firefox23+、IE9+ 中按 F12,然后查看 Net/Network 標(biāo)簽)。Servlet 容器將會確定每個進入的 HTTP 請求的 Cookie 頭中是否存在名為JSESSIONID 的 cookie,然后用它的值(session ID)從服務(wù)端內(nèi)存中找到關(guān)聯(lián)的 HttpSession。

你可以在 web.xml 中設(shè)置 session-timeout ,默認值為 30 分鐘。超時到達之前 HttpSession 會一直存活。所以當(dāng)客戶端不再訪問該 web 應(yīng)用超過 30 分鐘后,Servlet 容器就會回收這個 session。后續(xù)每個請求,即使指定 cookie 名稱也不能再訪問到相同的 session。Servlet 容器會創(chuàng)建一個新的 Cookie。

另一方面,客戶端上的 session cookie 有一個默認存活時間,該事件和該瀏覽器實例運行時間一樣長。所以,當(dāng)客戶端關(guān)閉該瀏覽器實例(所有標(biāo)簽和窗口)后,這個 session 就會被客戶端回收。新瀏覽器實例不再發(fā)送與該 session 關(guān)聯(lián)的 cookie。一個新的 request.getSession() 將會返回新的 HttpSession 并設(shè)置一個擁有新 session ID 的 cookie。

概述

  • ServletContext 與 web 應(yīng)用存活時間一樣長。它被所有 session 中的所有請求共享。

  • 只要客戶端一直與相同瀏覽器實例的web應(yīng)用交互并且沒有超時,HttpSession就會存在。

  • HttpServletRequestHttpServletResponse 的存活時間為客戶端發(fā)送完成到完整的響應(yīng)(web 頁面)到達的這段時間。不會被其他地方共享。

  • 所有 Servlet、FilterListener 對象在 web 應(yīng)用運行時都是活躍的。它們被所有 session 中的請求共享。

  • 你設(shè)置在 HttpServletRequest、HttpServletResponseHttpSession 中的所有屬性在問題中的對象存活時都會一直保持存活。

線程安全

即便如此,你最關(guān)心的可能是線程安全。你現(xiàn)在應(yīng)該學(xué)習(xí)到 Servlet 和 filter 被所有請求共享。那是 Java 的一個優(yōu)點,使得多個不同線程(讀取 HTTP 請求)可以使用同一個實例。否則為每個請求重新創(chuàng)建線程的開銷實在過于昂貴。

但你應(yīng)該也意識到永遠不要將任何 request 或 session 域中的數(shù)據(jù)賦值給 servlet 或 filter 的實例變量。它將會被所有其他 session 中的所有請求共享。那是非線程安全的!下面的示例對這種情況進行了展示:

 

  1. public class ExampleServlet extends HttpServlet { 
  2.  
  3.     private Object thisIsNOTThreadSafe; 
  4.  
  5.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
  6.         Object thisIsThreadSafe; 
  7.  
  8.         thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests! 
  9.         thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe. 
  10.     } 

請參考:

 

 
責(zé)任編輯:王雪燕 來源: ImportNew
相關(guān)推薦

2009-07-06 16:16:33

Servlet容器工作

2009-07-03 17:41:47

JavaBean Se

2009-06-30 10:33:00

JSP JavaBeaServlet

2011-12-14 10:31:43

2009-07-06 09:23:51

Servlet定義

2011-03-11 09:41:17

JavaGC

2021-05-08 07:57:17

ServletFilter設(shè)計模式

2009-06-18 13:31:03

Spring工作原理

2009-08-14 13:19:23

2024-05-28 00:00:02

Java線程程序

2023-09-19 22:47:39

Java內(nèi)存

2011-12-07 14:25:33

JavaNIO

2015-09-02 08:57:56

JavaHashMap工作原理

2020-06-15 07:00:00

GitOpsKubernetesDevOps

2009-07-16 10:23:30

iBATIS工作原理

2009-06-15 15:57:21

Spring工作原理

2010-09-25 15:19:01

2021-07-16 11:35:20

Java線程池代碼

2009-07-08 09:35:53

Java ServleServlet 3.0

2010-09-25 13:11:48

DHCP工作原理
點贊
收藏

51CTO技術(shù)棧公眾號