日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Servlet原理解析

發布時間:2023/12/14 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Servlet原理解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 1 Servlet介紹
    • 1.1 簡介
    • 1.2 Servlet生命周期
      • 1.2.1 生命周期
      • 1.2.2 servlet配置
      • 1.2.3 servlet中load-on-startup作用
    • 1.3 Servlet接口
      • 1.3.1 HttpServlet
        • 1.3.1.1 service,doGet,doPost區別
      • 1.3.2 表單提交中get和post方式區別
        • 1.3.2.1 表單中區別
        • 1.3.2.2 http中區別
  • 2 Servlet原理
    • 2.1 工作原理
      • 2.1.1 問題引入
      • 2.1.2 Servlet容器啟動
      • 2.1.3 HttpServletRequest 與 HttpServletResponse
      • 2.1.4 HttpSession
      • 2.1.5 ServletContext
      • 2.1.6 線程安全
    • 2.2 Servlet單例多線程
      • 2.2.1 Servlet如何處理多個請求訪問
      • 2.2.2 Servlet容器如何采用單實例多線程的方式來處理請求
      • 2.2.3 Servlet多實例
      • 2.2.4 容器概念理解

1 Servlet介紹

1.1 簡介

Servlet是一種運行于服務器端的Java應用程序,具有獨立于平臺和協議的特性,可以生成動態的Web頁面,它擔當客戶請求與服務器響應的中間層 ,有特殊的技術規范:必須繼承某個特定父類;必須配置之后才能執行;有特定的生命周期
Servlet是在Java代碼中嵌入頁面代碼,JSP是在頁面代碼中嵌入Java代碼
JSP不能執行,必須轉譯成Servlet并編譯成class后才能執行,Servlet是學好JSP的基礎,能了解JSP的底層運作方式

1.2 Servlet生命周期

1.2.1 生命周期

每個servlet實例的生命周期中只有三種類型的事情,分別對應于由servlet容器所調用的三個方法:

  • init() 初始化時期:
    當servlet第一次被裝載的時候由servlet容器調用init(),且只調用一次,默認情況下調用超類的init()方法。
  • service()運行時期:
    接受客戶請求并決定調用何種doXXX方法,并將處理結果返回到客戶端。
  • destroy()結束時期:
    為可選方法,釋放不用的servlet實例所占內存和資源。

Servlet的生命周期可以歸納為以下幾步:

  • Servlet創建一個Servlet實例;
  • Servlet調用Servlet的init()方法;
  • 客戶發送請求到Servlet;
  • Servlet創建一個請求對象和一個響應對象
  • Servlet調用service()方法,傳遞請求和響應對象作為參數;
  • service()方法獲得請求對象的參數,處理請求,訪問其他資源。
  • service()方法通過響應對象將結果傳遞給Server,最終到達客戶端。
  • 對于更多的相同客戶端請求, Servlet將創建新的請求和響應對象,仍然激活此Servlet的service方法,傳遞新的參數對象,不需在初始化一次。
  • 當Servlet不再需要Servlet時(關閉時)調用destory()方法。
  • 1.2.2 servlet配置

    <servlet><servlet-name>Servlet的名稱</servlet-name><servlet-class>該servlet類的路徑</servlet-class><init-param><param-name>參數名</param-name><param-value>參數值</param-value></init-param><jsp-file>/路徑/XXX.JSP </jsp-file><load-on-startup>表示web站臺被啟動時,自動加載該servlet的優先級別,越小越優先加載</load-on-startup> </servlet> <servlet-mapping><servlet-name>對應的servlet-name名稱</servlet-name><url-pattern>在項目運行時用以訪問的URL </url-pattern> </servlet-mapping>

    url-pattern 取值:1、可以與具體的某個Servlet對應。2、也可以用/* 來指定所有的頁面,更多關于servlet路徑配置可以點此連接查看

    1.2.3 servlet中load-on-startup作用

    像上面的servlet配置中的標簽<load-on-startup>,注意到它里面包含了這段配置:<load-on-startup>1</load-on-startup>,那么這個配置有什么作用呢?

  • load-on-startup元素標記容器是否在啟動的時候就加載這個servlet(實例化并調用其init()方法)。
  • 它的值必須是一個整數,表示servlet應該被載入的順序
  • 當值為0或者大于0時,表示容器在應用啟動時就加載并初始化這個servlet;
  • 當值小于0或者沒有指定時,則表示容器在該servlet被選擇時才會去加載。
  • 正數的值越小,該servlet的優先級越高,應用啟動時就越先加載。
  • 當值相同時,容器就會自己選擇順序來加載。
  • 所以,<load-on-startup>x</load-on-startup>,中x的取值1,2,3,4,5代表的是優先級,而非啟動延遲時間

    1.3 Servlet接口

    1.3.1 HttpServlet

    HttpServlet類,httpServlet中各種接受請求處理的方法

    方法名描述
    doGet()處理http的get請求
    doPost()處理http的post請求,主要用于發送HTML文本中FORM的內容
    doHead()用于處理HEADER請求
    doPut()處理http的put請求,模仿 ftp發送
    doDelete()處理http的delete請求
    doOptions()該操作自動決定支持什么HTTP方法
    doTrace()處理HTTP的trace請求

    發送請求的三種基本方式
    地址欄直接鍵入地址(默認get方式) 例如:在地址欄輸入:http://127.0.0.1/jsp2/index.jsp?a=2
    使用表單提交(默認get方式)只有使用表單的method=post才是post提交
    點擊超鏈接(默認get方式)

    1.3.1.1 service,doGet,doPost區別

    HttpServlet 里的三個方法service(HttpServletRequest req, HttpServletResponse resp) ,doGet(HttpServletRequest req, HttpServletResponse resp), doPost(HttpServletRequest req, HttpServletResponse res)的區別和聯系

    在servlet中默認情況下,無論是get還是post提交過來都會經過service()方法來處理,然后轉向到doGet或是doPost方法,可以查看HttpServlet 類的service方法

    protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{String method = req.getMethod();if(method.equals("GET")){long lastModified = getLastModified(req);if(lastModified == -1L){doGet(req, resp);} else{long ifModifiedSince = req.getDateHeader("If-Modified-Since");if(ifModifiedSince < (lastModified / 1000L) * 1000L){maybeSetLastModified(resp, lastModified);doGet(req, resp);} else{resp.setStatus(304);}}} elseif(method.equals("HEAD")){long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} elseif(method.equals("POST"))doPost(req, resp);elseif(method.equals("PUT"))doPut(req, resp);elseif(method.equals("DELETE"))doDelete(req, resp);elseif(method.equals("OPTIONS"))doOptions(req, resp);elseif(method.equals("TRACE")){doTrace(req, resp);} else{String errMsg = lStrings.getString("http.method_not_implemented");Object errArgs[] = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(501, errMsg);}}

    從上面可以看出 這里的service是用來轉向的,但是如果在自己的servlet類中覆蓋了service方法,比如說你的service是下面這樣的,那么這時service就不是用來轉向的,而是用來處理業務的,現在不論客戶端是用pos還是get來請求此servlet,都會執行service方法也只能執行servlet方法,不會去執行doPost或是doGet方法

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { res.getOutputStream().print( "image is <img src='images/downcoin.gif'></img><br>"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request,response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletOutputStream out=response.getOutputStream(); String[] args=(String[])request.getParameterValues("fruit"); for(int i=0;i<args.length;i++){ out.print(args[i]+"<br>"); } }

    所以,我們在寫servlet的時候,一般都是重寫doGet或doPost方法,不會管service方法

    1.3.2 表單提交中get和post方式區別

    1.3.2.1 表單中區別

    表單提交中get和post方式的區別有5點

  • get是從服務器上獲取數據,post是向服務器傳送數據。
  • get是把參數數據隊列加到提交表單的ACTION屬性所指的URL中,值和表單內各個字段一 一對應,在URL中可以看到。post是通過HTTPpost機制,將表單內各個字段與其內容放置在HTML HEADER內一起傳送到ACTION屬性所指的URL地址。用戶看不到這個過程。
  • 對于get方式,服務器端用Request.QueryString獲取變量的值,對于post方式,服務器端用Request.Form獲取提交的數據。
  • get傳送的數據量較小,不能大于2KB。post傳送的數據量較大,一般被默認為不受限制
  • get安全性非常低,post安全性較高。
  • 1.3.2.2 http中區別

    HTTP請求:get與post方法的區別:
    HTTP定義了與服務器交互的不同方法,最基本的方法是 get 和 post。事實上 get 適用于多數請求,而保留 post僅用于更新站點。根據 HTTP規范,get 用于信息獲取,而且應該是安全的和冪等的。所謂安全的意味著該操作用于獲取信息而非修改信息。換句話說,get 請求一般不應產生副作用。冪等的意味著對同一URL的多個請求應該返回同樣的結果。完整的定義并不像看起來那樣嚴格。從根本上講,其目標是當用戶打開一個鏈接時,可以確信從自身的角度來看沒有改變資源。比如,新聞站點的頭版不斷更新。雖然第二次請求會返回不同的一批新聞,該操作仍然被認為是安全的和冪等的,因為它總是返回當前的新聞。反之亦然。但 post請求就不那么輕松了。post表示可能改變服務器上的資源的請求。

    在FORM提交的時候,如果不指定Method,則默認為get請求,Form中提交的數據將會附加在url之后,以?分開與url分開。字母數字字符原樣發送,但空格轉換為+號,其它符號轉換為%XX, 其中XX為該符號以16進制表示的ASCII(或ISOLatin-1)值。get請求請提交的數據放置在HTTP請求協議頭中,而post提交的數據則 放在實體數據中;
    get方式提交的數據最多只能有1024字節,而post則沒有此限制
    在表單里使用post和get有什么區別
    在Form里面,可以使用post也可以使用get。它們都是method的合法取值。但是,post和get方法在使用上至少有兩點不同:

  • get方法通過URL請求來傳遞用戶的輸入。post方法通過另外的形式。
  • get方式的提交需要用Request.QueryString來取得變量的值,而post方式提交時,必須通過Request.Form來訪問提交的內容。
  • 2 Servlet原理

    2.1 工作原理

    2.1.1 問題引入

    Servlet是如何工作的?Servlet 如何實例化、共享變量、并進行多線程處理?
    假設有一個運行了大量 Servlet 的 web 服務器。通過 Servlet 之間傳輸信息得到 Servlet 上下文,并設置 session 變量。現在,如果有兩名或更多使用者向這個服務發送請求,接下來 session 變量會發生什么變化?究竟是所有用戶都是用共同的變量?還是不同的用戶使用的變量都不一樣?如果是后者,服務器如何區分不同用戶?
    如果有n名用戶訪問一個特定的 Servlet,那么該 Servlet 是僅在第一個用戶首次訪問的時候實例化,還是分別為每個用戶實例化?

    2.1.2 Servlet容器啟動

    當 Servlet 容器(比如 Apache Tomcat)啟動后,會部署和加載所有 web 應用。當web應用被加載,Servlet 容器會創建一次ServletContext,然后將其保存在服務器的內存中。
    web應用的web.xml被解析,找到其中所有 servlet、filter 和 Listener 或 @WebServlet、@WebFilter 和@WebListener 注解的內容,創建一次并保存到服務器的內存中。對于所有過濾器會立即調用init()。當 Servlet 容器停止,將卸載所有 web 應用,調用所有初始化的 Servlet 和過濾器的destroy() 方法,最后回收 ServletContext 和所有 Servlet、Filter 與 Listener實例。
    當Servlet 配置的load-on-startup或者 @WebServlet(loadOnStartup) 設置了一個大于 0 的值,則同樣會在啟動的時候立即調用 init() 方法。
    load-on-startup中的值表示那些 Servlet 會以相同順序初始化。如果配置的值相同,會遵循 web.xml 中指定的順序或 @WebServlet類加載的順序。另外,如果不設置 load-on-startup 值,init() 方法只在第一次HTTP請求命中問題中的Servlet時才被調用

    2.1.3 HttpServletRequest 與 HttpServletResponse

    Servlet 容器附加在一個 web 服務上,這個 web 服務會在某個端口號上監聽 HTTP 請求,在開發環境中這個端口通常為 8080,生產環境中通常為 80。當客戶端(web 瀏覽器)發送了一個 HTTP 請求,Servlet 容器會創建新的 HttpServletRequest 和 HttpServletResponse 對象,傳遞給已創建好并且請求的 URL 匹配 url-pattern 的 Filter 和 Servlet 實例中的方法,所有工作都在同一個線程中處理。
    request 對象可以訪問所有該 HTTP 請求中的信息,例如 request header 和 request body。response 對象提供需要的控制和發送 HTTP 響應方法,例如設置 header 和 body(通常會帶有 JSP 文件中的 HTML 內容)。提交并完成HTTP 響應后,將回收 request 和 response 對象。

    2.1.4 HttpSession

    當用戶第一次訪問該 web 應用時,會通過 request.getSession() 第一次獲得 HttpSession。之后 Servlet 容器將會創建 HttpSession,生成一個唯一的 ID(可以通過 session.getId() 獲取)并儲存在服務器內存中。然后 Servlet 容器在該次 HTTP 響應的 Set-Cookie 頭部設置一個 Cookie,以JSESSIONID 作為 Cookie 名字,那個唯一的 session ID 作為 Cookie 的值。
    按照 HTTP cookie 規則(正常 web 瀏覽器和 web 服務端必須遵循的標準),當 cookie 有效時,要求客戶端(瀏覽器)在后續請求的 Cookie 頭中返回這個 cookie。
    使用瀏覽器內置的HTTP流量監控器,Servlet容器將會確定每個進入的 HTTP 請求的 Cookie 頭中是否存在名為JSESSIONID 的 cookie,然后用它的值(session ID)從服務端內存中找到關聯的 HttpSession。
    可以在 web.xml 中設置 session-timeout ,默認值為 30 分鐘。超時到達之前 HttpSession 會一直存活。所以當客戶端不再訪問該 web 應用超過 30 分鐘后,Servlet 容器就會回收這個 session。后續每個請求,即使指定 cookie 名稱也不能再訪問到相同的 session。Servlet 容器會創建一個新的 Cookie。
    另一方面,客戶端上的 session cookie 有一個默認存活時間,該事件和該瀏覽器實例運行時間一樣長。所以,當客戶端關閉該瀏覽器實例(所有標簽和窗口)后,這個 session 就會被客戶端回收。新瀏覽器實例不再發送與該 session 關聯的 cookie。一個新的 request.getSession() 將會返回新的HttpSession 并設置一個擁有新 session ID 的 cookie

    2.1.5 ServletContext

    ServletContext 與 web 應用存活時間一樣長。它被所有 session 中的所有請求共享。
    只要客戶端一直與相同瀏覽器實例的web應用交互并且沒有超時HttpSession就會存在。
    HttpServletRequest和 HttpServletResponse 的存活時間為客戶端發送完成到完整的響應(web頁面)到達的這段時間。不會被其他地方共享。
    所有 Servlet、Filter 和 Listener 對象在web 應用運行時都是活躍的。它們被所有 session 中的請求共享。
    設置在 HttpServletRequest、HttpServletResponse 和 HttpSession 中的所有屬性在問題中的對象存活時都會一直保持存活。

    2.1.6 線程安全

    即便如此,最關心的可能是線程安全。現在應該學習到 Servlet 和 filter 被所有請求共享。那是 Java 的一個優點,使得多個不同線程(讀取 HTTP 請求)可以使用同一個實例。否則為每個請求重新創建線程的開銷實在過于昂貴。
    但應該也意識到永遠不要將任何 request 或 session 域中的數據賦值給 servlet 或 filter 的實例變量。它將會被所有其他 session 中的所有請求共享。那是非線程安全的
    下面的示例對這種情況進行了展示:

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

    由于當客戶端第一次請求某一個JSP文件時,服務端把該JSP編譯成一個CLASS文件,并創建一個該類的實例,然后創建一個線程處理CLIENT端的請求。如果有多個客戶端同時請求該JSP文件,則服務端會創建多個線程。每個客戶端請求對應一個線程。以多線程方式執行可大大降低對系統的資源需求,提高系統的并發量及響應時間.

    對JSP中可能用的的變量說明如下:

    • 實例變量: 實例變量是在堆中分配的,并被屬于該實例的所有線程共享,所以不是線程安全的. JSP系統提供的8個類變量:JSP中用到的OUT,REQUEST,RESPONSE,CONFIG,PAGE,PAGECONXT是線程安全的(因為每個線程對應的request,respone對象都是不一樣的,不存在共享問題), SESSION,APPLICATION在整個系統內被使用,所以不是線程安全的
      ServletContext:(線程是不安全的) ServletContext是可以多線程同時讀/寫屬性的,線程是不安全的。要對屬性的讀寫進行同步處理或者進行深度Clone()。所以在Servlet上下文中盡可能少量保存會被修改(寫)的數據,可以采取其他方式在多個Servlet中共享,比方我們可以使用單例模式來處理共享數據。
      HttpSession:(線程是不安全的) HttpSession對象在用戶會話期間存在,只能在處理屬于同一個Session的請求的線程中被訪問,因此Session對象的屬性訪問理論上是線程安全的。 當用戶打開多個同屬于一個進程的瀏覽器窗口,在這些窗口的訪問屬于同一個Session,會出現多次請求,需要多個工作線程來處理請求,可能造成同時多線程讀寫屬性。這時我們需要對屬性的讀寫進行同步處理:使用同步塊Synchronized和使用讀/寫器來解決。 ServletRequest:(線程是安全的) 對于每一個請求,由一個工作線程來執行,都會創建有一個新的ServletRequest對象,所以ServletRequest對象只能在一個線程中被訪問。ServletRequest是線程安全的。
      注意:ServletRequest對象在service方法的范圍內是有效的,不要試圖在service方法結束后仍然保存請求對象的引用
    • 局部變量: 局部變量在堆棧中分配,因為每個線程都有它自己的堆棧空間,所以是線程安全的.
    • 靜態類: 靜態類不用被實例化,就可直接使用,也不是線程安全的.
    • 外部資源: 在程序中可能會有多個線程或進程同時操作同一個資源(如:多個線程或進程同時對一個文件進行寫操作).此時也要注意同步問題. 使它以單線程方式執行,這時,仍然只有一個實例,所有客戶端的請求以串行方式執行。這樣會降低系統的性能

    2.2 Servlet單例多線程

    2.2.1 Servlet如何處理多個請求訪問

    Servlet容器默認是采用單實例多線程的方式處理多個請求的:

  • 當web服務器啟動的時候(或客戶端發送請求到服務器時),Servlet就被加載并實例化(只存在一個Servlet實例);
  • 容器初始化Servlet主要就是讀取配置文件(例如tomcat,可以通過servlet.xml的<Connector>設置線程池中線程數目,初始化線程池通過web.xml,初始化每個參數值等等。
  • 當請求到達時,Servlet容器通過調度線程(Dispatchaer Thread) 調度它管理下線程池中等待執行的線程(Worker Thread)給請求者;
  • 線程執行Servlet的service方法;
  • 請求結束,放回線程池,等待被調用; (注意:避免使用實例變量(成員變量),因為如果存在成員變量,可能發生多線程同時訪問該資源時,都來操作它,照成數據的不一致,因此產生線程安全問題)
  • 從上面可以看出:

  • Servlet單實例,減少了產生servlet的開銷;
  • 通過線程池來響應多個請求,提高了請求的響應時間;
  • Servlet容器并不關心到達的Servlet請求訪問的是否是同一個Servlet還是另一個Servlet,直接分配給它一個新的線程;如果是同一個Servlet的多個請求,那么Servlet的service方法將在多線程中并發的執行;
  • 每一個請求由ServletRequest對象來接受請求,由ServletResponse對象來響應該請求; Servlet/JSP技術和ASP、PHP等相比,由于其多線程運行而具有很高的執行效率。由于Servlet/JSP默認是以多線程模式執行的,所以,在編寫代碼時需要非常細致地考慮多線程的安全性問題。
  • 2.2.2 Servlet容器如何采用單實例多線程的方式來處理請求

    Java的內存模型JMM(Java Memory Model) JMM主要是為了規定了線程和內存之間的一些關系。根據JMM的設計,系統存在一個主內存(Main Memory),Java中所有實例變量都儲存在主存中,對于所有線程都是共享的。每條線程都有自己的工作內存(Working Memory),工作內存由緩存和堆棧兩部分組成,緩存中保存的是主存中變量的拷貝,緩存可能并不總和主存同步,也就是緩存中變量的修改可能沒有立刻寫到主存中;堆棧中保存的是線程的局部變量,線程之間無法相互直接訪問堆棧中的變量。根據JMM,我們可以將論文中所討論的Servlet實例的內存模型抽象為圖所示的模型。

    工作者線程Work Thread:執行代碼的一組線程。
    調度線程Dispatcher Thread:每個線程都具有分配給它的線程優先級,線程是根據優先級調度執行的。
    Servlet采用多線程來處理多個請求同時訪問。servlet依賴于一個線程池來服務請求。線程池實際上是一系列的工作者線程集合。Servlet使用一個調度線程來管理工作者線程。 當容器收到一個Servlet請求,調度線程從線程池中選出一個工作者線程,將請求傳遞給該工作者線程,然后由該線程來執行Servlet的service方法。當這個線程正在執行的時候,容器收到另外一個請求,調度線程同樣從線程池中選出另一個工作者線程來服務新的請求,容器并不關心這個請求是否訪問的是同一個Servlet.當容器同時收到對同一個Servlet的多個請求的時候,那么這個Servlet的service()方法將在多線程中并發執行。 Servlet容器默認采用單實例多線程的方式來處理請求,這樣減少產生Servlet實例的開銷,提升了對請求的響應時間,對于Tomcat可以在server.xml中通過<Connector>元素設置線程池中線程的數目。
    就實現來說,調度者線程類所擔負的責任如其名字,該類的責任是調度線程,只需要利用自己的屬性完成自己的責任。所以該類是承擔了責任的,并且該類的責任又集中到唯一的單體對象中。而其他對象又依賴于該特定對象所承擔的責任,我們就需要得到該特定對象。那該類就是一個單例模式的實現了

    2.2.3 Servlet多實例

    服務器可以使用多個實例來處理請求,代替單個實例的請求排隊帶來的效益問題。服務器創建一個Servlet類的多個Servlet實例組成的實例池,對于每個請求分配Servlet實例進行響應處理,之后放回到實例池中等待下此請求。這樣就造成并發訪問的問題。此時,局部變量(字段)也是安全的,但對于全局變量和共享數據是不安全的,需要進行同步處理。而對于這樣多實例的情況SingleThreadModel接口并不能解決并發訪問問題。 SingleThreadModel接口在servlet規范中已經被廢棄了。

    Servlet并非只是單例的. 當container開始啟動,或是客戶端發出請求服務時,Container會按照容器的配置負責加載和實例化一個Servlet(也可以配置為多個,不過一般不這么干).不過一般來說一個servlet只會有一個實例。

  • Struts2的Action是原型,非單實例的;會對每一個請求,產生一個Action的實例來處理。
  • Struts1的Action,Spring的Ioc容器管理的bean默認是單實例的. Struts1 Action是單實例的,spring mvc的controller也是如此。因此開發時要求必須是線程安全的,因為僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能作的事,并且要在開發時特別小心。Action資源必須是線程安全的或同步的。 Spring的Ioc容器管理的bean 默認是單實例的。 Struts2 Action對象為每一個請求產生一個實例,因此沒有線程安全問題。(實際上,servlet容器給每個請求產生許多可丟棄的對象,并且不會導致性能和垃圾回收問題)。 當Spring管理Struts2的Action時,bean默認是單實例的,可以通過配置參數將其設置為原型。(scope=prototype )
  • 2.2.4 容器概念理解

    Servlet容器,Web容器,應用服務器
    Servlet容器的主要任務就是管理Servlet的生命周期;
    Web容器也稱之為web服務器,主要任務就是管理和部署web應用的; 應用服務器的功能非常強大,不僅可以管理和部署web應用,也可以部署EJB應用,實現容器管理的事務等等。。。
    Web服務器就是跟基于HTTP的請求打交道,而EJB容器更多是跟數據庫,事務管理等服務接口交互,所以應用服務器的功能是很多的。 常見的web服務器就是Tomcat,但Tomcat同樣也是Servlet服務器; 常見的應用服務器有WebLogic,WebSphere,但都是收費的; 沒有Servlet容器,可以用Web容器直接訪問靜態Html頁面,比如安裝了apache等;如果需要顯示Jsp/Servlet,就需要安裝一個Servlet容器;但是光有servlet容器也是不夠的,它需要被解析為html顯示,所以仍需要一個web容器;所以,我們常把web容器和Servlet容器視為一體,因為他們兩個容器都有對方的功能實現了,都沒有獨立的存在了,比如tomcat)

    總結

    以上是生活随笔為你收集整理的Servlet原理解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。