21 道JavaWeb經(jīng)典面試題總結(jié)
1.說說 Servlet 的基本架構(gòu)
Servlet 是 Java Web 應用程序中處理客戶端請求并生成響應的重要組件,它的基本架構(gòu)可以分為以下幾個部分:
(1)Servlet 接口
Servlet 接口是所有 Servlet 類必須實現(xiàn)的接口,它定義了處理客戶端請求的常見方法,包括初始化、請求處理和銷毀等。在 Servlet 接口中,最常見的方法包括 init()、service() 和 destroy()。
(2)Servlet 容器
Servlet 容器是負責管理和運行 Servlet 的環(huán)境,可以理解為一個 Web 服務器或者應用服務器。Servlet 容器負責加載、實例化、初始化、調(diào)用服務方法和銷毀 Servlet 實例。在 Java 中,常見的 Servlet 容器包括 Tomcat、Jetty、Undertow 等。
(3)部署描述符
部署描述符是一個 XML 文件,它包含了關于 Servlet 的配置信息,包括 Servlet 名稱、URL 映射、初始化參數(shù)、引入其他 Servlet 或過濾器等。在 Java Web 應用中,典型的部署描述符是 web.xml 文件。
(4)Servlet 類
Servlet 類是實現(xiàn) Servlet 接口的具體類,它負責處理客戶端請求并生成響應。在 Servlet 類中,通常實現(xiàn)了 init()、service() 和 destroy() 方法,也可以覆蓋 doGet()、doPost() 等方法來處理不同類型的請求。
(5)請求和響應對象
在 Servlet 中,可以通過請求對象 HttpServletRequest 和響應對象 HttpServletResponse 來與客戶端進行通信。請求對象封裝了客戶端發(fā)送的請求信息,而響應對象負責生成服務器返回的響應內(nèi)容。
當客戶端發(fā)送請求時,Servlet 容器會根據(jù)部署描述符中的映射信息選擇合適的 Servlet 實例來處理請求。Servlet 實例接收到請求后,調(diào)用其 service() 方法來處理請求并生成響應。然后響應會被發(fā)回客戶端。
這就是 Servlet 的基本架構(gòu),它提供了一個在 Java Web 應用程序中處理客戶端請求的標準化方式,并且可以通過實現(xiàn)不同的 Servlet 類來實現(xiàn)特定的業(yè)務邏輯。
2.說一說 Servlet 的生命周期?
Servlet 的生命周期包括的階段:
加載和實例化:當容器啟動時,會根據(jù)部署描述符(web.xml)或注解等配置信息加載并實例化 Servlet。容器會創(chuàng)建 ServletConfig 對象,并將部署描述符中的初始化參數(shù)傳遞給 Servlet 實例。
初始化:在 Servlet 實例化后,容器會調(diào)用其 init() 方法來執(zhí)行一些初始化任務。通??梢栽?init() 方法中進行一些初始化操作,比如建立數(shù)據(jù)庫連接、加載配置文件等。init() 方法只會在 Servlet 實例第一次被創(chuàng)建時執(zhí)行一次。
服務請求:一旦初始化完成,Servlet 就可以響應客戶端的請求。當客戶端發(fā)送請求時,Servlet 容器會調(diào)用 Servlet 的 service() 方法來處理請求。service() 方法會根據(jù)請求類型(GET、POST 等)來調(diào)用相應的 doGet()、doPost() 等方法。這是 Servlet 生命周期中最頻繁調(diào)用的階段,用來處理客戶端的請求并生成響應。
銷毀:當 Servlet 容器決定將 Servlet 實例銷毀時,會調(diào)用其 destroy() 方法。在 destroy() 方法中可以清理資源,比如關閉數(shù)據(jù)庫連接、釋放內(nèi)存等。Servlet 實例銷毀時會執(zhí)行 destroy() 方法,代表 Servlet 生命周期的結(jié)束。
3.如何實現(xiàn)一個自定義的 servlet?
- 創(chuàng)建一個新的 Java 類,并讓它繼承 HttpServlet 類。這樣可以確保你的類成為一個 Servlet;
- 在你的自定義類中,你需要重寫 doGet 或 doPost 方法。這些方法將定義你的 Servlet 處理請求的行為;
- 將你的自定義 Servlet 編譯成 .class 文件,并將它放在 WEB-INF/classes 目錄下(或者將 .class 文件打包成 .war 文件放在 webapps 目錄下)。你還需要在 web.xml 文件中配置你的 Servlet。
如下所示:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.nezha.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
根據(jù)實際需求,你可能需要處理初始化、銷毀等其他方法。另外,你也可以使用注解來代替 web.xml 的配置。
4.servlet中有哪些核心類?都有什么特點?
(1)Servlet 接口
Servlet 接口是所有 servlet 類的基礎接口。所有的 Servlet 類都必須實現(xiàn)這個接口,并且提供處理客戶端請求的邏輯。在 Servlet 接口中定義了一系列的生命周期方法,包括 init、service 和 destroy。通過實現(xiàn)這些方法,可以在 servlet 實例的生命周期中執(zhí)行初始化、處理請求和資源銷毀等操作。
(2)HttpServlet
HttpServlet 是 Servlet 的抽象子類,它提供了專門用于處理 HTTP 請求的方法。它進一步擴展了 GenericServlet,并增加了處理 HTTP GET、POST、PUT、DELETE 等請求的方法。大多數(shù) Web 應用程序中的 Servlet 都是繼承自 HttpServlet。
(3)HttpServletRequest
代表客戶端的請求信息,包含了請求行、請求頭和請求體等信息,提供了獲取參數(shù)、請求頭數(shù)據(jù)、請求屬性等方法。
(4)HttpServletResponse
代表服務器的響應信息,用于構(gòu)建和發(fā)送回客戶端的響應,提供了設置狀態(tài)碼、添加響應頭、寫入響應體等方法。
5.什么情況下調(diào)用 doGet()和 doPost()?
當客戶端發(fā)送的請求使用了 HTTP GET 方法時,Servlet 容器會調(diào)用 Servlet 的 doGet() 方法來處理該請求。
當客戶端發(fā)送的請求使用了 HTTP POST 方法時,Servlet 容器會調(diào)用 Servlet 的 doPost() 方法來處理該請求。
GET請求通常用于請求數(shù)據(jù)或查詢信息,它的特點是請求的數(shù)據(jù)會附加在URL之后,并且是可見的。因此,GET請求不適合傳輸敏感信息,如密碼或銀行賬戶信息。
POST 請求通常用于向服務器發(fā)送數(shù)據(jù),進行數(shù)據(jù)修改、提交或發(fā)送較大的數(shù)據(jù)等操作。比如,向服務器提交表單數(shù)據(jù)。
6.request.getAttribute() 和 request.getParameter() 有何區(qū)別?
request.getParameter() 方法用于獲取客戶端請求中的查詢參數(shù)(GET 請求)或表單參數(shù)(POST 請求)。它返回的是一個字符串類型,用于表示指定參數(shù)名對應的參數(shù)值。
request.getAttribute() 方法用于獲取在服務器端范圍內(nèi)共享的數(shù)據(jù),這些數(shù)據(jù)通常是通過服務器端代碼設置到請求域中的。它返回的是一個 Object 類型的數(shù)據(jù),因此需要進行類型轉(zhuǎn)換才能使用。通過 request.setAttribute() 方法設置的數(shù)據(jù)可以在同一個請求中的不同資源(如 Servlet、JSP)之間共享。
7.forward 和 redirect 的區(qū)別?
可以從三個方面來回答,處理方式、應用場景、效率。
forward是服務器內(nèi)部的資源轉(zhuǎn)發(fā),瀏覽器地址欄不會發(fā)生變化,用戶無法感知到轉(zhuǎn)發(fā)過程。而redirect則是服務端通知客戶端進行頁面跳轉(zhuǎn),客戶端會發(fā)起新的請求到指定的URL,因此瀏覽器地址欄會顯示新的地址。
forward通常用于需要根據(jù)用戶角色或其他條件來展示不同內(nèi)容的情況,比如登錄后根據(jù)用戶權限轉(zhuǎn)發(fā)到不同的管理頁面。而redirect則常用于需要用戶重新登錄或在完成某項操作后返回上一個頁面的場景,如注銷后重定向到登錄頁面。
forward由于是服務器內(nèi)部處理,通常效率較高,因為它避免了額外的網(wǎng)絡請求和響應的延遲。而redirect因為涉及到客戶端的多次請求和響應,所以效率相對較低。
8.jsp 有哪些內(nèi)置對象?作用分別是什么?
- request,客戶端的請求,用于獲取客戶端通過HTTP協(xié)議發(fā)送到服務器的數(shù)據(jù),包括請求頭、請求參數(shù)、請求方式等。
- response,服務器的響應,用于向客戶端發(fā)送數(shù)據(jù),包括設置響應頭、發(fā)送響應體等。
- out,用于向客戶端輸出內(nèi)容,是JSP頁面中的輸出流。
- session,表示客戶端與服務器之間的一次會話,用于保存用戶的狀態(tài)信息,如用戶登錄信息、購物車數(shù)據(jù)等。
- application,代表整個Web應用的上下文,用于保存全局的信息,這些信息在整個Web應用中都是可見的。
- pageContext,提供了對JSP頁面內(nèi)各種對象(如request、response、session等)的訪問,以及用于查找其他資源的API。
- config,用于獲取JSP頁面的初始化參數(shù)和Servlet上下文信息。
- page,代表JSP頁面本身,可以通過它訪問JSP頁面的屬性和方法。
- exception,當JSP頁面發(fā)生異常時,該對象會被自動設置為拋出的異常對象,允許在JSP頁面中處理異常。
9.jsp 有哪些動作?作用分別是什么?
在JSP(Java Server Pages)中,動作(Action)是一種特殊的標簽,用于執(zhí)行特定的操作,比如轉(zhuǎn)發(fā)請求、包含文件、設置屬性等。
- include 動作,將其他JSP或HTML頁面的內(nèi)容嵌入到當前JSP頁面中,使得頁面可以動態(tài)包含其他頁面的內(nèi)容。
- forward 動作,將請求轉(zhuǎn)發(fā)到其他資源,比如轉(zhuǎn)發(fā)到另一個JSP頁面或Servlet,這樣可以共享請求屬性,并且URL會改變。
- param 動作,用于設置請求參數(shù),可以將參數(shù)添加到包含或轉(zhuǎn)發(fā)的請求中。
- setProperty 動作,用于設置JavaBean屬性。
- getProperty 動作,用于獲取JavaBean的屬性值。
- useBean 動作,用于實例化JavaBean,如果JavaBean不存在則創(chuàng)建,存在則不創(chuàng)建。
- plugin 動作,用于包含插件,一般用于內(nèi)嵌多媒體對象。
- jsp:element 動作,在JSP頁面中生成XML元素。
- jsp:attribute 動作,定義自定義標簽的屬性,并為屬性設置默認值。
- jsp:body 動作,在自定義標簽中定義標簽體的內(nèi)容。
這些動作能夠在JSP頁面中實現(xiàn)各種功能,如包含內(nèi)容、轉(zhuǎn)發(fā)請求、操作JavaBean等。它們使JSP頁面能夠更加靈活和強大。
10.JSP 中動態(tài) INCLUDE 與靜態(tài) INCLUDE 的區(qū)別?
(1)動態(tài) include:
- 動態(tài) include 是通過 jsp:include 動作實現(xiàn)的,可以在運行時動態(tài)地包含另一個 JSP 頁面或 Servlet 的輸出。
- 可以根據(jù)特定的條件或邏輯來決定包含哪個頁面,也可以在循環(huán)中動態(tài)包含不同的頁面。
- 使用 jsp:include 標簽,例如:<jsp:include page="included.jsp"/>
(2)靜態(tài) include:
- 靜態(tài) include 是在編譯時將指定的 JSP 頁面或 HTML 文件合并到當前 JSP 頁面中,形成一個單一的頁面。
- 在 JSP 頁面執(zhí)行之前,包含的內(nèi)容已經(jīng)靜態(tài)地合并到當前頁面中了。
- 使用 <%@ include file="included.jsp" %> 語法,其中 file 屬性指定要包含的文件。
動態(tài) include 是在運行時進行包含,可以動態(tài)決定包含哪個頁面,而靜態(tài) include 是在編譯時靜態(tài)地將指定文件的內(nèi)容合并到當前頁面中,運行時無法改變包含的內(nèi)容。具體使用時需要根據(jù)實際場景來選擇使用動態(tài) include 還是靜態(tài) include。
11.jsp 和 servlet 有什么區(qū)別?
Servlet是用Java編寫的服務器端程序,它的主要功能是處理客戶端的請求并生成動態(tài)Web內(nèi)容。Servlet是Java Web應用的基礎,負責接收請求、處理請求、生成響應。
JSP本質(zhì)上是一種特殊的Servlet,它允許開發(fā)者在HTML頁面中直接嵌入Java代碼片段(scriptlets)、JSP動作、JSP指令以及表達式等,以生成動態(tài)Web頁面。JSP的主要目的是使開發(fā)者能夠更容易地創(chuàng)建動態(tài)Web頁面,而無需編寫大量的Java代碼。
12.說一下 jsp 的 4 種作用域?
(1)Page作用域
最窄的作用域,它僅限于當前的JSP頁面。當頁面處理完成后,存儲在page作用域中的任何數(shù)據(jù)都將被丟棄。此作用域通常用于存儲僅在當前頁面中使用的臨時變量。
(2)Request作用域
這個作用域涵蓋了單個HTTP請求及其對應的響應。在此作用域中定義的任何數(shù)據(jù)都可以在同一請求中的多個頁面之間共享,但當請求處理完畢后,這些數(shù)據(jù)就會失效。這適用于跨多個JSP頁面?zhèn)鬟f數(shù)據(jù)的情況。
(3)Session作用域
此作用域與特定的用戶會話相關聯(lián)。在一個用戶訪問網(wǎng)站期間,該用戶的所有請求都可以訪問session作用域中的數(shù)據(jù)。當用戶離開網(wǎng)站或會話超時,session中的數(shù)據(jù)才會被清除。這通常用于存儲需要跟蹤用戶狀態(tài)的信息,比如購物車內(nèi)容或者登錄信息。
(4)Application作用域
最寬泛的作用域,它適用于整個Web應用程序。在此作用域中聲明的數(shù)據(jù)對所有用戶和所有請求都是可見的,并且在整個應用程序的生命周期內(nèi)都有效。常用于存儲應用程序級別的信息,例如配置參數(shù)或統(tǒng)計信息。
13.session 和 cookie 有什么區(qū)別?
Session和Cookie的主要區(qū)別在于存儲位置、存儲容量以及存儲有效期。
- 存儲位置:Cookie數(shù)據(jù)信息存放在客戶端瀏覽器中,而Session的數(shù)據(jù)信息存放在服務器上。
- 存儲容量:Cookie的存儲容量較小,一般不超過4KB,而Session的存儲容量理論上沒有限制,但為了服務器性能考慮,通常不會存放過多數(shù)據(jù)。
- 存儲有效期:Cookie可以設置為長時間保持,甚至可以設置到期時間來實現(xiàn)長期存儲,而Session的失效時間通常較短,一般為會話結(jié)束或瀏覽器關閉時失效。
14.如果客戶端禁止 cookie 能實現(xiàn) session 還能用嗎?
一般默認情況下,在會話中,服務器存儲 session 的 sessionid 是通過 cookie 存到瀏覽器里。
如果瀏覽器禁用了 cookie,瀏覽器請求服務器無法攜帶 sessionid,服務器無法識別請求中的用戶身份,session失效。
但是可以通過其他方法在禁用 cookie 的情況下,可以繼續(xù)使用session。
- 通過url重寫,把 sessionid 作為參數(shù)追加的原 url 中,后續(xù)的瀏覽器與服務器交互中攜帶 sessionid 參數(shù)。
- 服務器的返回數(shù)據(jù)中包含 sessionid,瀏覽器發(fā)送請求時,攜帶 sessionid 參數(shù)。
- 通過 Http 協(xié)議其他 header 字段,服務器每次返回時設置該 header 字段信息,瀏覽器中 js 讀取該 header 字段,請求服務器時,js設置攜帶該 header 字段。
15.Token、Cookie、Session的區(qū)別?
Token 是一種用于認證和授權的令牌,通常由服務器生成并發(fā)送給客戶端??蛻舳嗽谑盏?Token 后,將其存儲在本地,然后在每次需要進行身份驗證或授權時使用該 Token。常見的 Token 包括 JWT (JSON Web Token) 和 OAuth Token。Token 在客戶端和服務器之間進行持久性的認證和授權,通常用于實現(xiàn)跨域身份驗證。
Cookie 是一種在客戶端中存儲的小型文本數(shù)據(jù),由服務器發(fā)送給客戶端,隨后在每次請求中通過 HTTP 頭部發(fā)送回服務器。通常用于存儲用戶的身份驗證信息、用戶設置、瀏覽歷史等。Cookie 是存儲在客戶端的,可以設置過期時間和路徑,不同頁面之間共享。
Session 是服務器端用于存儲用戶會話狀態(tài)的機制,通常使用 Session ID 來標識用戶會話。當用戶第一次訪問服務器時,服務器會為其創(chuàng)建一個 session,然后將 session ID 存儲在 cookie 或者 URL 中,用于在該用戶的后續(xù)請求中進行身份驗證和狀態(tài)管理。Session 數(shù)據(jù)存儲在服務器端,相對于 Cookie 更安全、更難被篡改,但也需要服務器維護和消耗更多的資源。
16.說一下 session 的工作原理?
- 客戶端發(fā)送請求:當用戶發(fā)送請求到服務器時,服務器會為該用戶創(chuàng)建一個唯一識別的 session ID,并將其返回給客戶端,在 HTTP Response Header 中可以使用 Set-Cookie 來設置這個 session ID。通常情況下,這個 session ID 會以一個名為 "JSESSIONID" 的 Cookie 存儲在客戶端。
- 服務器端存儲會話數(shù)據(jù):當服務器收到客戶端的請求時,會檢查請求中是否包含有效的 session ID。如果存在有效的 session ID,服務器就會使用這個 session ID 來獲取對應的會話數(shù)據(jù)。如果沒有有效的 session ID,服務器會創(chuàng)建一個新的 session,并為其分配一個新的 session ID。服務器端會針對每個 session ID 維護一個對應的會話數(shù)據(jù)存儲,可以存儲用戶的身份驗證信息、用戶設置、購物車數(shù)據(jù)等用戶會話相關的信息。
- 與客戶端交互:在處理完客戶端的請求后,服務器會將 session ID 返回給客戶端,在 HTTP Response Header 中使用 Set-Cookie。客戶端會存儲這個 session ID,在后續(xù)的請求中將其包含在 HTTP 請求頭中,服務器通過 session ID 來識別用戶,并獲取對應的會話數(shù)據(jù)進行處理。
- 會話超時和銷毀:在一定的時間間隔后,若用戶沒有活動,服務器可能會認為該會話已經(jīng)超時并銷毀會話數(shù)據(jù),釋放資源。這樣可以保證服務器的資源不會被無效的會話占用。
簡而言之,Session 的工作原理是通過在服務器端創(chuàng)建、存儲和管理會話數(shù)據(jù),并通過在客戶端使用 session ID 進行身份驗證和狀態(tài)管理,實現(xiàn)用戶會話的跟蹤和狀態(tài)維護。
17.http 響應碼 301 和 302 代表的是什么?有什么區(qū)別?
http 響應碼 301:
- 301表示請求的資源已經(jīng)永久移動到了一個新的 URL 地址。
- 當服務器返回 301 狀態(tài)碼時,它會在響應頭中包含一個 Location 屬性,客戶端會根據(jù)該屬性進行重定向。
- 客戶端在后續(xù)的請求中會直接請求新的 URL 地址。
http 響應碼 302:
- 302示請求的資源暫時性地移動到了一個新的 URL 地址。
- 客戶端會在收到響應后根據(jù) Location 頭信息跳轉(zhuǎn)到新的 URL。但客戶端在后續(xù)的請求中會繼續(xù)請求原來的 URL 地址。
- 302 響應不會被瀏覽器緩存,每次請求時會重新執(zhí)行跳轉(zhuǎn)。
18.tomcat 如何調(diào)優(yōu)?
調(diào)整Tomcat的性能和優(yōu)化配置是提高Web應用程序性能的重要步驟。
以下是一些優(yōu)化Tomcat的常見方法:
(1)調(diào)整內(nèi)存分配
將JVM最大堆大?。?Xmx)和初始堆大?。?Xms)設置為合適的值,以確保應用程序運行期間有足夠的內(nèi)存,一般建議堆的最大值設置為可用內(nèi)存的最大值的 80%。
調(diào)整新生代和老年代的比例,可以使用參數(shù) -XX:NewSize 和 -XX:MaxNewSize 調(diào)整新生代堆大小。
(2)調(diào)整線程池和連接池
配置Tomcat的連接和線程池大小,確保它能夠處理預期的并發(fā)請求,可以通過調(diào)整 maxThreads、minSpareThreads 和 maxConnections 等參數(shù)進行配置。
使用合適的連接池,例如對于數(shù)據(jù)庫連接,可以使用連接池來管理連接,以提高性能和資源利用率。
(3)啟用壓縮
啟用Tomcat的壓縮功能,可以通過配置啟用GZIP壓縮,減小傳輸內(nèi)容的大小,提高性能。
(4)優(yōu)化靜態(tài)資源處理
使用獨立的Web服務器(如Nginx或Apache)作為前置服務器,處理靜態(tài)資源和緩存請求,減輕Tomcat服務器負擔。
針對Tomcat內(nèi)置的靜態(tài)資源緩存,可以通過配置添加Expires或Cache-Control響應頭來緩存靜態(tài)資源。
(5)監(jiān)控和調(diào)整
使用監(jiān)控工具如JConsole、JVisualVM或者性能工具如VisualVM來監(jiān)控Tomcat性能,識別性能瓶頸并做相應調(diào)整。
根據(jù)監(jiān)控結(jié)果,適時調(diào)整JVM和Tomcat的配置參數(shù),以優(yōu)化性能。
19.如何增加 tomcat 的連接數(shù)?
- maxConnections參數(shù)決定了Tomcat能夠同時處理的最大連接數(shù)。在BIO模式下,默認最大連接數(shù)是它的最大線程數(shù)(一般設置為200)。
- maxThreads參數(shù)表示Tomcat接收客戶端請求的最大線程數(shù),即同時處理任務的個數(shù)。在高并發(fā)的I/O密集型應用中,這個值可以設置為1000左右以提升處理能力。
- 使用NIO模式,因為NIO是非阻塞的IO,可以提高Tomcat在高并發(fā)環(huán)境下的性能。
- 調(diào)整acceptCount,當線程數(shù)量達到maxThreads設置的值時,acceptCount決定了所能接受的最大排隊數(shù)量,超過這個值,新的請求會被拒絕。
- 如果單個Tomcat實例無法滿足需求,可以考慮使用負載均衡器將流量分發(fā)到多個Tomcat實例。
20.如何增加Tomcat的內(nèi)存?
要增加 Tomcat 的內(nèi)存,你需要調(diào)整 Tomcat 運行時的JVM參數(shù)。以下是一般步驟:
(1)找到 Tomcat 的啟動腳本
Tomcat 的啟動腳本通常位于 bin 目錄下,具體文件名可能是 catalina.sh (Linux) 或 catalina.bat (Windows)。
(2)編輯啟動腳本,設置 JVM 參數(shù)
在啟動腳本中找到 JAVA_OPTS 或 CATALINA_OPTS 變量,并增加 -Xmx 和 -Xms 參數(shù)來分別設置最大堆和初始堆大小。
示例:
CATALINA_OPTS="$CATALINA_OPTS -Xms512m -Xmx1024m" 這將會將初始堆大小設置為512MB,最大堆大小設置為1024MB。你可以根據(jù)實際情況調(diào)整這些值。
(3)重啟 Tomcat 服務器
保存啟動腳本并重啟 Tomcat 服務器,以應用新的內(nèi)存設置。
21.Tomcat 有幾種部署方式?
① 將WAR包或文件夾直接放置到Tomcat的webapps目錄下,Tomcat會自動解壓并部署項目,缺點是需要重啟項目。
② 不想放在webapps下,也可以在Tomcat的server.xml文件中配置標簽,添加標簽來指定項目的WAR包路徑。(一般采用①)。
③ 可以將Tomcat運行在Docker容器中,通過Dockerfile或者docker-compose文件來管理和部署應用程序。
④ 可以將 Tomcat 應用部署到云服務提供商(如AWS、Azure、Google Cloud等)的云服務器上,實現(xiàn)靈活的彈性部署,按需分配資源。