1、struts2工作流程
Struts 2框架本身大致可以分為3個部分:
核心控制器FilterDispatcher、業務控制器Action和用戶實現的企業業務邏輯組件。
核心控制器FilterDispatcher是Struts 2框架的基礎,包含了框架內部的控制流程和處理機制。
業務控制器Action和業務邏輯組件是需要用戶來自己實現的。
用戶在開發Action和業務邏輯組件的同時,還需要編寫相關的配置文件,
供核心控制器FilterDispatcher來使用。
基本簡要流程如下:
1 、客戶端初始化一個指向Servlet容器的請求;
2、 這個請求經過一系列的過濾器(Filter)
(這些過濾器中有一個叫做ActionContextCleanUp的可選過濾器,這個過濾器對于Struts2和其他框架的集成很有幫助,例如:SiteMesh Plugin)
3 、接著FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否需要調用某個Action
4、如果ActionMapper決定需要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5、ActionProxy通過Configuration Manager詢問框架的配置文件,找到需要調用的Action類
6、ActionProxy創建一個ActionInvocation的實例。
7、ActionInvocation實例使用命名模式來調用,在調用Action的過程前后,涉及到相關攔截器(Intercepter)的調用。
8、一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果 。返回結果通常是(但不總是,也可 能是另外的一個Action鏈)一個需要被表示的JSP或者FreeMarker的模版。 在表示的過程中可以使用Struts2 框架中繼承的標簽。 在這個過程中需要涉及到ActionMapper
9、響應的返回是通過我們在web.xml中配置的過濾器
10、如果ActionContextCleanUp是當前使用的,則FilterDispatecher將不會清理sreadlocal ActionContext;如果ActionContextCleanUp不使用,則將會去清理sreadlocals。
2、Struts2的設計模式
MVC模式: web應用程序啟動時就會加載并初始化ActionServler。用戶提交表單時,一個配置好的ActionForm對象被創建,并被填入表單相應的數據,ActionServler根據Struts-config.xml文件配置好的設置決定是否需要表單驗證,如果需要就調用ActionForm的Validate()驗證后選擇將請求發送到哪個Action,如果Action不存在,ActionServlet會先創建這個對象,然后調用Action的execute()方法。Execute()從ActionForm對象中獲取數據,完成業務邏輯,返回一個ActionForward對象,ActionServlet再把客戶請求轉發給ActionForward對象指定的jsp組件,ActionForward對象指定的jsp生成動態的網頁,返回給客戶。
3、攔截器和過濾器的區別
1、攔截器是基于java反射機制的,而過濾器是基于函數回調的。
2、過濾器依賴于servlet容器,而攔截器不依賴于servlet容器。
3、攔截器只能對Action請求起作用,而過濾器則可以對幾乎所有請求起作用。
4、攔截器可以訪問Action上下文、值棧里的對象,而過濾器不能。
5、在Action的生命周期中,攔截器可以多次調用,而過濾器只能在容器初始化時被調用一次。
4、struts1于struts2的比較
1、Action 類:
Struts1要求Action類繼承一個抽象基類。Struts1的一個普遍問題是使用抽象類編程而不是接口。
Struts 2 Action類可以實現一個Action接口,也可實現其他接口,使可選和定制的服務成為可能。Struts2提供一個ActionSupport基類去 實現常用的接口。Action接口不是必須的,任何有execute標識的POJO對象都可以用作Struts2的Action對象。
2、線程模式:
Struts1 Action是單例模式并且必須是線程安全的,因為僅有Action的一個實例來處理所有的請求。單例策略限制了Struts1 Action能作的事,并且要在開發時特別小心。Action資源必須是線程安全的或同步的。
Struts2 Action對象為每一個請求產生一個實例,因此沒有線程安全問題。(實際上,servlet容器給每個請求產生許多可丟棄的對象,并且不會導致性能和垃圾回收問題)
3、Servlet 依賴:
Struts1 Action 依賴于Servlet API ,因為當一個Action被調用時HttpServletRequest 和 HttpServletResponse 被傳遞給execute方法。
Struts 2 Action不依賴于容器,允許Action脫離容器單獨被測試。如果需要,Struts2 Action仍然可以訪問初始的request和response。但是,其他的元素減少或者消除了直接訪問HttpServetRequest 和 HttpServletResponse的必要性。
4、可測性:
測試Struts1 Action的一個主要問題是execute方法暴露了servlet API(這使得測試要依賴于容器)。一個第三方擴展--Struts TestCase--提供了一套Struts1的模擬對象(來進行測試)。
Struts 2 Action可以通過初始化、設置屬性、調用方法來測試,“依賴注入”支持也使測試更容易。
5、捕獲輸入:
Struts1 使用ActionForm對象捕獲輸入。所有的ActionForm必須繼承一個基類。因為其他JavaBean不能用作ActionForm,開發者經 常創建多余的類捕獲輸入。動態Bean(DynaBeans)可以作為創建傳統ActionForm的選擇,但是,開發者可能是在重新描述(創建)已經存 在的JavaBean(仍然會導致有冗余的javabean)。
Struts 2直接使用Action屬性作為輸入屬性,消除了對第二個輸入對象的需求。輸入屬性可能是有自己(子)屬性的rich對象類型。Action屬性能夠通過 web頁面上的taglibs訪問。Struts2也支持ActionForm模式。rich對象類型,包括業務對象,能夠用作輸入/輸出對象。這種 ModelDriven 特性簡化了taglib對POJO輸入對象的引用。
6、表達式語言:
Struts1 整合了JSTL,因此使用JSTL EL。這種EL有基本對象圖遍歷,但是對集合和索引屬性的支持很弱。
Struts2可以使用JSTL,但是也支持一個更強大和靈活的表達式語言-- "Object Graph Notation Language " (OGNL).
7、綁定值到頁面(view):
Struts 1使用標準JSP機制把對象綁定到頁面中來訪問。
Struts 2 使用 "ValueStack "技術,使taglib能夠訪問值而不需要把你的頁面(view)和對象綁定起來。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重用頁面(view)。
8、類型轉換:
Struts 1 ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進行類型轉換。每個類一個轉換器,對每一個實例來說是不可配置的。
Struts2 使用OGNL進行類型轉換。提供基本和常用對象的轉換器。
9、校驗:
Struts 1支持在ActionForm的validate方法中手動校驗,或者通過Commons Validator的擴展來校驗。同一個類可以有不同的校驗內容,但不能校驗子對象。
Struts2支持通過validate方法和XWork校驗框架來進行校驗。XWork校驗框架使用為屬性類類型定義的校驗和內容校驗,來支持chain校驗子屬性
10、Action執行的控制:
Struts1支持每一個模塊有單獨的Request Processors(生命周期),但是模塊中的所有Action必須共享相同的生命周期。
Struts2支持通過攔截器堆棧(Interceptor Stacks)為每一個Action創建不同的生命周期。堆棧能夠根據需要和不同的Action一起使用。
5、為什么要使用Struts2
Struts2 是一個相當強大的Java Web開源框架,是一個基于POJO的Action的MVC Web框架。它基于當年的Webwork和XWork框架,繼承其優點,同時做了相當的改進。
1.Struts2基于MVC架構,框架結構清晰,開發流程一目了然,開發人員可以很好的掌控開發的過程。
2.使用OGNL進行參數傳遞
OGNL提供了在Struts2里訪問各種作用域中的數據的簡單方式,你可以方便的獲取Request,Attribute,Application,Session,Parameters中的數據。大大簡化了開發人員在獲取這些數據時的代碼量。
3.強大的攔截器
Struts2 的攔截器是一個Action級別的AOP,Struts2中的許多特性都是通過攔截器來實現的,例如異常處理,文件上傳,驗證等。攔截器是可配置與重用的,可以將一些通用的功能如:登錄驗證,權限驗證等置于攔截器中以完成一些Java Web項目中比較通用的功能。在我實現的的一Web項目中,就是使用Struts2的攔截器來完成了系統中的權限驗證功能。
4.易于測試
Struts2的Action都是簡單的POJO,這樣可以方便的對Struts2的Action編寫測試用例,大大方便了5Java Web項目的測試。
5.易于擴展的插件機制
在Struts2添加擴展是一件愉快而輕松的事情,只需要將所需要的Jar包放到WEB-INF/lib文件夾中,在struts.xml中作一些簡單的設置就可以實現擴展。
6.模塊化管理
Struts2已經把模塊化作為了體系架構中的基本思想,可以通過三種方法來將應用程序模塊化:將配置信息拆分成多個文件把自包含的應用模塊創建為插件創建新的框架特性,即將與特定應用無關的新功能組織成插件,以添加到多個應用中去。
7.全局結果與聲明式異常
為應用程序添加全局的Result,和在配置文件中對異常進行處理,這樣當處理過程中出現指定異常時,可以跳轉到特定頁面。
他的如此之多的優點,是很多人比較的青睞,與spring ,Hibernate進行結合,組成了現在比較流行的ssh框架,當然每個公司都要自己的框架,也是ssh變異的產品。
6、struts2有哪些優點?
1)在軟件設計上Struts2的應用可以不依賴于Servlet API和struts API。 Struts2的這種設計屬于無侵入式設計;
2)攔截器,實現如參數攔截注入等功能;
3)類型轉換器,可以把特殊的請求參數轉換成需要的類型;
4)多種表現層技術,如:JSP、freeMarker、Velocity等;
5)Struts2的輸入校驗可以對指定某個方法進行校驗;
6)提供了全局范圍、包范圍和Action范圍的國際化資源文件管理實現
7、struts2是如何啟動的?
struts2框架是通過Filter啟動的,即StrutsPrepareAndExecuteFilter,此過濾器為struts2的核心過濾器;
StrutsPrepareAndExecuteFilter的init()方法中將會讀取類路徑下默認的配置文件struts.xml完成初始化操作。struts2讀取到struts.xml的內容后,是將內容封裝進javabean對象然后存放在內存中,以后用戶的每次請求處理將使用內存中的數據,而不是每次請求都讀取struts.xml文件。
8、struts2框架的核心控制器是什么?它有什么作用?
1)Struts2框架的核心控制器是StrutsPrepareAndExecuteFilter。
2)作用:
負責攔截由<url-pattern>/*</url-pattern>指定的所有用戶請求,當用戶請求到達時,該Filter會過濾用戶的請求。默認情況下,如果用戶請求的路徑 不帶后綴或者后綴以.action結尾,這時請求將被轉入struts2框架處理,否則struts2框架將略過該請求的處理。
可以通過常量"struts.action.extension"修改action的后綴,如:
<constant name="struts.action.extension" value="do"/>
如果用戶需要指定多個請求后綴,則多個后綴之間以英文逗號(,)隔開。
<constant name="struts.action.extension" value="do,go"/>
9、struts2配置文件的加載順序?
struts.xml ——> struts.properties
常量可以在struts.xml或struts.properties中配置,如果在多個文件中配置了同一個常量,則后一個文件中配置的常量值會覆蓋前面文件中配置的常量值.
struts.xml文件的作用:通知Struts2框架加載對應的Action資源
10、struts2常量的修改方式?
常量可以在struts.xml或struts.properties中配置,兩種配置方式如下:
1)在struts.xml文件中配置常量
<constant name="struts.action.extension" value="do"/>
2)在struts.properties中配置常量(struts.properties文件放置在src下):
struts.action.extension=do
11、struts2如何訪問HttpServletRequest、HttpSession、ServletContext三個域對象?
方案一:
HttpServletRequest request =ServletActionContext.getRequest();
HttpServletResponse response =ServletActionContext.getResponse();
HttpSession session= request.getSession();
ServletContext servletContext=ServletActionContext.getServletContext();
方案二:
類 implements ServletRequestAware,ServletResponseAware,SessionAware,ServletContextAware
注意:框架自動傳入對應的域對象
12、struts2是如何管理action的?這種管理方式有什么好處?
struts2框架中使用包來管理Action,包的作用和java中的類包是非常類似的。
主要用于管理一組業務功能相關的action。在實際應用中,我們應該把一組業務功能相關的Action放在同一個包下。
13、struts2中的默認包struts-default有什么作用?
1)struts-default包是由struts內置的,它定義了struts2內部的眾多攔截器和Result類型,而Struts2很多核心的功能都是通過這些內置的攔截器實現,如:從請求中
把請求參數封裝到action、文件上傳和數據驗證等等都是通過攔截器實現的。當包繼承了struts-default包才能使用struts2為我們提供的這些功能。
2)struts-default包是在struts-default.xml中定義,struts-default.xml也是Struts2默認配置文件。 Struts2每次都會自動加載 struts-default.xml文件。
3)通常每個包都應該繼承struts-default包。
14、struts2如何對指定的方法進行驗證?
1)validate()方法會校驗action中所有與execute方法簽名相同的方法;
2)要校驗指定的方法通過重寫validateXxx()方法實現, validateXxx()只會校驗action中方法名為Xxx的方法。其中Xxx的第一個字母要大寫;
3)當某個數據校驗失敗時,調用addFieldError()方法往系統的fieldErrors添加校驗失敗信息(為了使用addFieldError()方法,action可以繼承ActionSupport), 如果系統 的fieldErrors包含失敗信息,struts2會將請求轉發到名為input的result;
4)在input視圖中可以通過<s:fielderror/>顯示失敗信息。
5)先執行validateXxxx()->validate()->如果出錯了,會轉發<result name="input"/>所指定的頁面,如果不出錯,會直接進行Action::execute()方法
15、struts2默認能解決get和post提交方式的亂碼問題嗎?
不能。struts.i18n.encoding=UTF-8屬性值只能解析POST提交下的亂碼問題。
16、請你寫出struts2中至少5個的默認攔截器?
fileUpload 提供文件上傳功能
i18n 記錄用戶選擇的locale
cookies 使用配置的name,value來是指cookies
checkbox 添加了checkbox自動處理代碼,將沒有選中的checkbox的內容設定為false,而html默認情況下不提交沒有選中的checkbox。
chain 讓前一個Action的屬性可以被后一個Action訪問,現在和chain類型的result()結合使用。
alias 在不同請求之間將請求參數在不同名字件轉換,請求內容不變
17、值棧ValueStack的原理與生命周期?
1)ValueStack貫穿整個 Action 的生命周期,保存在request域中,所以ValueStack和request的生命周期一樣。當Struts2接受一個請求時,會迅速創建ActionContext,
ValueStack,action。然后把action存放進ValueStack,所以action的實例變量可以被OGNL訪問。 請求來的時候,action、ValueStack的生命開始,請求結束,action、 ValueStack的生命結束;
2)action是多例的,和Servlet不一樣,Servelt是單例的;
3)每個action的都有一個對應的值棧,值棧存放的數據類型是該action的實例,以及該action中的實例變量,Action對象默認保存在棧頂;
4)ValueStack本質上就是一個ArrayList;
5)關于ContextMap,Struts 會把下面這些映射壓入 ContextMap 中:
parameters : 該 Map 中包含當前請求的請求參數
request : 該 Map 中包含當前 request 對象中的所有屬性 session :該 Map 中包含當前 session 對象中的所有屬性
application :該 Map 中包含當前 application 對象中的所有屬性
attr:該 Map 按如下順序來檢索某個屬性: request, session, application
6)使用OGNL訪問值棧的內容時,不需要#號,而訪問request、session、application、attr時,需要加#號;
7)注意: Struts2中,OGNL表達式需要配合Struts標簽才可以使用。如:<s:property value="name"/>
8)在struts2配置文件中引用ognl表達式 ,引用值棧的值 ,此時使用的"$",而不是#或者%;
18、ActionContext、ServletContext、pageContext的區別?
1)ActionContext是當前的Action的上下文環境,通過ActionContext可以獲取到request、session、ServletContext等與Action有關的對象的引用;
2)ServletContext是域對象,一個web應用中只有一個ServletContext,生命周期伴隨整個web應用;
3)pageContext是JSP中的最重要的一個內置對象,可以通過pageContext獲取其他域對象的應用,同時它是一個域對象,作用范圍只針對當前頁面,當前頁面結束時,pageContext銷毀,生命周期是JSP四個域對象中最小的。
19、result的type屬性中有哪幾種結果類型?
一共10種:
dispatcher
struts默認的結果類型,把控制權轉發給應用程序里的某個資源不能把控制權轉發給一個外部資源,若需要把控制權重定向到一個外部資源, 應該使用
redirect結果類型
redirect 把響應重定向到另一個資源(包括一個外部資源)
redirectAction 把響應重定向到另一個 Action
freemarker、velocity、chain、httpheader、xslt、plainText、stream
20、攔截器的生命周期與工作過程?
1)每個攔截器都是實現了Interceptor接口的 Java 類;
2)init(): 該方法將在攔截器被創建后立即被調用, 它在攔截器的生命周期內只被調用一次. 可以在該方法中對相關資源進行必要的初始化;
3)intercept(ActionInvocation invocation): 每攔截一個動作請求, 該方法就會被調用一次;
4)destroy: 該方法將在攔截器被銷毀之前被調用, 它在攔截器的生命周期內也只被調用一次;
5)struts2中有內置了18個攔截器。
21、struts2如何完成文件的上傳?
1、JSP頁面:
1)JSP頁面的上傳文件的組件:<s: file name=”upload” />,如果需要一次上傳多個文件, 就必須使用多個 file 標簽, 但它們的名字必須是相同的,即: name=“xxx”的值必須一樣;
2)必須把表單的enctype屬性設置為:multipart/form-data;
3)表單的方法必須為post,因為post提交的數據在消息體中,而無大小限制。
2、對應的action:
1)在 Action 中新添加 3 個和文件上傳相關的屬性;
2)如果是上傳單個文件, uploadImage屬性的類型就是 java.io.File, 它代表被上傳的文件, 第二個和第三個屬性的類型是 String, 它們分別代表上傳文件的文件名和文件類型,定義方式是分別是:
jsp頁面file組件的名稱+ContentType, jsp頁面file組件的名稱+FileName
3)如果上上傳多個文件, 可以使用數組或 List