1. 預備知識: a) 攔截器配置 在struts-default.xml中定義了很多攔截器,,這些攔截器就是用來完成許多強勁功能的保證,,而且可以根據已定義的若干攔截器中的某幾個攔截器構建成interceptor-stack攔截器棧,其實攔截器棧還可以由攔截器棧組成,。即從Struts2高層的角度來看,二者沒有什么區(qū)別,。 我們可以在<package/>中增加這樣一行<default-interceptor-ref name="攔截器的名字"/>即表示將該攔截器作為整個包的默認攔截器,,它會自動附加到我們的每一個Action中。并且在一個<package/>中只能使用<default-interceptor-ref/>定義一個默認的攔截器,。 若<action/>沒有引用任何一個攔截器,,那么默認的defaultStack會自動附加到<action/>中 若<action/>手工引用任何一個攔截器,那么默認的defaultStack就不會附加到<action/>中 若還想使用默認攔截器,,則只能再通過手工方式導入<interceptor-ref name="defaultStack"/> 如果沒有引用Struts2的默認攔截器,,那么就會影響到整體的輸入校驗即其它的一些功能 Struts2攔截器的配置和使用都很easy,這得益于其底層的良好架構以及它的AOP的思想 該攔截器即標準的AOP思想,,代碼不寫死到Action里,,而是根據配置靈活附加到Action中 使用上,Struts2攔截器并不復雜,。但實現(xiàn)上,,是很復雜的,其底層用到了動態(tài)代理的機制
b) 造成重復提交主要的兩個原因:
1) 一是,,服務器處理時間久,。當用戶在表單中填完信息,點擊“提交”按鈕后,,由于服務器反應時間過長沒能及時看到響應信息,,或者出于其它目的,再次點擊“提交”按鈕,,從而導致在服務器端接收到兩條或多條相同的信息,。如果信息需要存儲到后臺數據庫中,如此以來就會產生數據庫操作異常提示信息,,以至于給用戶帶來錯誤信息提示,,從而給用戶的使用帶來不便,。
2) 二是,forward跳轉引起的重復提交,。當用戶將信息提交到服務器,,服務器響應采用forward方式調轉到下一個頁面后,此時地址欄中顯示的是上個頁面的URL,,若刷新當前頁面,,瀏覽器會將再次提交用戶先前輸入的數據,就會再次出現(xiàn)表單重復提交的問題,。當然你可以選擇redirect方式跳轉頁面,,這樣就不會出現(xiàn)重復提交的問題;但有時為了達到某種效果或式,。者出于網站安全的目的需要隱藏網頁跳轉,,而不得不采用forward跳轉方
c) 對token的簡單理解: 1)當用戶首次訪問包含表單的頁面時,服務器會在這次會話中創(chuàng)建一個session對象,,并產生一個令牌值,,然后將這個令牌值作為隱藏輸入域的值,隨表單一起發(fā)送到服務器端,,同時將令牌值保存到Session中,。 2) 當用戶提交頁面時,服務器首先判斷請求參數中的令牌值和Session中保存的令牌值是否相等,,若相等,,則清楚Session中的令牌值,然后執(zhí)行數據處理操作,。如果不相等,,則提示用戶已經提交過了表單,同時產生一個新的令牌值,,保存到Session中,。當用戶重新訪問提交數據頁面時,將新產生的令牌值作為隱藏輸入域的值,。
注意問題:請簡述客戶端跳轉和服務器端跳轉之間的區(qū)別 客戶端跳轉時用HttPservletResopse對象的sendRedirect函數實現(xiàn),服務器端跳轉是使用RequestDispather對象的forward方法實現(xiàn)的,。這兩者之間的區(qū)別主要體現(xiàn)在三個方面: 1. 使用服務器端跳轉時,,客戶瀏覽器的地址欄并不會顯示目標地址的URL,而是用客戶端跳轉時,,地址欄當中會顯示目標資源的URL,; 2. 服務器端跳轉是由客戶端發(fā)送一個請求,請求一個服務器資源——如JSP和Servlet——,,這個資源又將請求轉到另一個服務器資源,,然后再給客戶端發(fā)送一個響應,,也就是說服務器端跳轉是客戶端發(fā)送一次請求,服務器端給出一次響應,;而客戶端跳轉的流程則不同,。客戶端同樣是發(fā)送一個請求給服務器端資源,,這個服務器資源會首先給客戶端一個響應,,客戶端再根據這個響應當中所包含的地址,再次向服務器端發(fā)送一個請求,,也就是說客戶端跳轉是兩次請求,,兩次響應; 3. 在進行客戶端跳轉和服務器端跳轉時,,都需要指定目標資源的URL,,如果這個路徑以“/”開始。在客戶端跳轉當中“/”代表的是應用服務器根目錄,,而在服務器端跳轉當中代表的是應用程序根目錄,。
2.開始解決 使用struts2 token攔截器 struts2的攔截器實現(xiàn)了防止表單重復提交的功能,即token攔截器,,在表單提交頁面寫上<s:token/>,,在struts.xml配置文件中相應的action上配置攔截器。此攔截器只能用在有form的提交請求上,。 Jsp頁面部分代碼:
在表單提交頁面寫上<s:token/> <s:form action="add" method="post"> <s:token /><!-- 防止表單重復提交 --> <s:textfield name="userName" label="用戶名"></s:textfield><br/> <s:password name="password" label="密碼"></s:password><br/> <s:submit /> </s:form>
在struts.xml配置文件中相應的action上配置攔截器 <action name="*" class="tutorial.UploadFiles" method="{1}"> <result name="filesShow"> /filesShow.jsp </result>
Struts2的內置攔截器:
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> <interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/> <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> <interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" /> <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" /> <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
核心提示:名稱 描述 alias 實現(xiàn)在不同請求中相似參數別名的轉換,。 autowiring 這是個自動裝配的攔截器,主要用于當Struts2和Spring整合時,,Struts2可以使用自動裝配的方式來訪問Spring容器中的Bean,。 chain 構建一個Action鏈,使當前Action可以訪問前一個Action的屬性 名稱 描述
alias 實現(xiàn) 在不同請求中相似參數別名的轉換,。
autowiring 這是個自動裝配的攔截器,,主要用于當Struts2和Spring整 合時,Struts2可以使用自動裝配的方式來訪問Spring容器中的Bean,。
chain 構建一個Action鏈,,使當 前Action可以訪問前一個Action的屬性,一般和<result type="chain" .../>一起使用,。
conversionError 這 是一個負責處理類型轉換錯誤的攔截器,,它負責將類型轉換錯誤從ActionContext中取出,并轉換成Action的FieldError錯誤,。
createSession 該 攔截器負責創(chuàng)建一個HttpSession對象,,主要用于那些需要有HttpSession對象才能正常工作的攔截器中。
debugging 當 使用Struts2的開發(fā)模式時,,這個攔截器會提供更多的調試信息,。
execAndWait 后臺執(zhí)行Action,,負責將等 待畫面發(fā)送給用戶。
exception 這個攔截器負責處理異常,,它將異常映射為結果,。
fileUpload 這 個攔截器主要用于文件上傳,它負責解析表單中文件域的內容,。
i18n 這是支持國際化的攔截器,,它負責把所選的語言、區(qū)域放入 用戶Session中,。
logger 這是一個負責日志記錄的攔截器,,主要是輸出Action的名字。
model-driven 這 是一個用于模型驅動的攔截器,,當某個Action類實現(xiàn)了ModelDriven接口時,,它負責把getModel()方法的結果堆入 ValueStack中。
scoped-model-driven 如果一個Action實現(xiàn)了一個 ScopedModelDriven接口,,該攔截器負責從指定生存范圍中找出指定的Modol,,并將通過setModel方法將該Model傳給 Action實例。
params 這是最基本的一個攔截器,,它負責解析HTTP請求中的參數,,并將參數值設置成Action對 應的屬性值。
prepare 如果action實現(xiàn)了Preparable接口,,將會調用該攔截器的prepare()方法,。
static-params 這 個攔截器負責將xml中<action>標簽下<param>標簽中的參數傳入action。
scope 這 是范圍轉換攔截器,,它可以將Action狀態(tài)信息保存到HttpSession范圍,,或者保存到ServletContext范圍內。
servlet-config 如 果某個Action需要直接訪問Servlet API,,就是通過這個攔截器實現(xiàn)的,。注意:盡量避免在Action中直接訪問Servlet API,這樣會導致Action與Servlet的高耦合,。
roles 這是一個JAAS(Java Authentication and Authorization Service,,Java授權和認證服務)攔截器,只有當瀏覽者取得合適的授權后,,才可以調用被該攔截器攔截的Action,。
timer 這 個攔截器負責輸出Action的執(zhí)行時間,這個攔截器在分析該Action的性能瓶頸時比較有用,。
token 這個攔截器主要 用于阻止重復提交,它檢查傳到Action中的token,,從而防止多次提交,。
token-session 這個攔截器的作用 與前一個基本類似,,只是它把token保存在HttpSession中。
validation 通過執(zhí)行在 xxxAction-validation.xml中定義的校驗器,,從而完成數據校驗,。
workflow 這個攔截器負責調用 Action類中的validate方法,如果校驗失敗,,則返回input的邏輯視圖,。
大部分時候,開發(fā)者無需手動控制這些攔截器,,因為struts-default.xml文件中已經配置了這些攔截器,,只要我們定義的包繼承 了系統(tǒng)的struts-default包,就可以直接使用這些攔截器,。 |
|