攔截器(interceptor)是Struts2最強大的特性之一,也能夠說是struts2的核心,攔截器可讓你在Action和result被執行以前或以後進行一些處理。同時,攔截器也可讓你將通用的代碼模塊化並做爲可重用的類。Struts2中的不少特性都是由攔截器來完成的。攔截是AOP的一種實現策略。在Webwork的中文文檔的解釋爲:攔截器是動態攔截Action調用的對象。它提供了一種機制可使開發者能夠定義在一個action執行的先後執行的代碼,也能夠在一個action執行前阻止其執行。同時也是提供了一種能夠提取action中可重用的部分的方式。談到攔截器,還有一個詞你們應該知道——攔截器鏈(Interceptor Chain,在Struts 2中稱爲攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其以前定義的順序被調用。css
大部分時候,攔截器方法都是經過代理的方式來調用的。Struts 2的攔截器實現相對簡單。當請求到達Struts 2的ServletDispatcher時,Struts 2會查找配置文件,並根據其配置實例化相對的攔截器對象,而後串成一個列表(list),最後一個一個地調用列表中的攔截器。Struts2攔截器是可插拔的,攔截器是AOP的一種實現。Struts2攔截器棧就是將攔截器按必定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,Struts2攔截器鏈中的攔截器就會按其以前定義的順序被調用。html
(1) 客戶端(Client)向Action發用一個請求(Request)java
(2) Container經過web.xml映射請求,並得到控制器(Controller)的名字web
(3) 容器(Container)調用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1之前調用FilterDispatcher,Struts2.1之後調用StrutsPrepareAndExecuteFilterajax
(4) 控制器(Controller)經過ActionMapper得到Action的信息算法
(5) 控制器(Controller)調用ActionProxyapache
(6) ActionProxy讀取struts.xml文件獲取action和interceptor stack的信息。服務器
(7) ActionProxy把request請求傳遞給ActionInvocationsession
(8) ActionInvocation依次調用action和interceptorapp
(9) 根據action的配置信息,產生result
(10) Result信息返回給ActionInvocation
(11) 產生一個HttpServletResponse響應
(12) 產生的響應行爲發送給客服端。
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.opensymphony.xwork2.interceptor; import com.opensymphony.xwork2.ActionInvocation; import java.io.Serializable; public interface Interceptor extends Serializable { void destroy(); void init(); String intercept(ActionInvocation var1) throws Exception; }
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package com.opensymphony.xwork2.interceptor; import com.opensymphony.xwork2.ActionInvocation; public abstract class AbstractInterceptor implements Interceptor { public AbstractInterceptor() { } public void init() { } public void destroy() { } public abstract String intercept(ActionInvocation var1) throws Exception; }
<!--定義攔截器,攔截器與攔截器棧的定義是相似,只是標籤不一樣--> <interceptors> <!--定義自定義攔截器--> <interceptor name="XXX" class="XXX"/> <!--定義攔截器棧--> <interceptor-stack name="XXX"> <interceptor-ref name="XXX"/> <interceptor-ref name="XXX"/> </interceptor-stack> </interceptors>
通常都會使用攔截器棧,由於除了咱們自定義的攔截器外,還須要使用系統默認的攔截器,defaultStack攔截器。
package com.turtle.demo2; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; import org.apache.struts2.ServletActionContext; public class InterceptorDemo extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { // 從session中取用戶 Object user = ServletActionContext.getRequest().getSession().getAttribute("user"); if(user == null){ ActionSupport actionSupport = (ActionSupport) actionInvocation.getAction(); actionSupport.addActionError("抱歉,用戶沒有登入"); return actionSupport.LOGIN; } // 放行 return actionInvocation.invoke(); } }
對於一個MVC框架而言,重點是實現兩部分:業務邏輯控制器部分和視圖頁面部分。Struts2做爲一個優秀的MVC框架,也把重點放在了這兩部分上。控制器主要由Action來提供支持,而視圖則是由大量的標籤來提供支持。
在JavaWeb中,Struts2標籤庫是一個比較完善,並且功能強大的標籤庫,它將全部標籤都統一到一個標籤庫中,從而簡化了標籤的使用,它還提供主題和模板的支持,極大地簡化了視圖頁面代碼的編寫,同時它還提供對ajax的支持,大大的豐富了視圖的表現效果。與JSTL(JSP Standard Library,JSP 標準標籤庫)相比,Struts2標籤庫更加易用和強大。
Struts2的UI標籤都是基於模板和主題的。所謂模板,就是一些代碼,Struts2標籤使用這些代碼渲染生成相應的HTML代碼。模板是一個UI標籤的外在表現形式,而且每一個標籤都會有本身對應的模板。若是爲全部的UI標籤提供樣式和視覺效果類似的模板, 那麼這一系列的模板就造成了一個主題。
Struts2 默認提供了4 種主題,分別爲 simple、xhtml、css_xhtml和Ajax。
simple主題:這是最簡單的主題,使用該主題時,每一個UI標籤只生成最基本的HTML元素,沒有任何附加功能。
xhtml主題:這是Struts2的默認主題,它對simple主題進行了擴展,提供了佈局功能、Label顯示名稱、以及與驗證框架和 國際化框架的集成。
css_xhtml:該主題是xhtml的擴展,在對xhtml的基礎之上添加對CSS的支持和控制。
Ajax:繼承自對xhtml,提供 Ajax支持。
這4種內建主題中,xhtml爲默認主題,但xhtml有必定的侷限性。由於它使用表格進行佈局,而且只支持每一行放一個表單項,這樣一來,一旦遇到複雜的頁面佈局,xhtml就難以勝任了。此時,就須要改變Struts2的默認主題。
一般,經過設置常量struts.ui.theme,來改變默認主題,具體作法是在struts.xml或者struts.properties文件中增長相應的配置。好比想要設置使用simple的主題,那麼須要在struts.xml中增長以下配置:
<constant name="struts.ui.theme" value="simple"/>
或者在struts.properties文件中增長以下配置:
struts.ui.theme=simple
if-elseif-else
<%--1、if elseif else的使用 --%> <% //存入請求域中一個學生的成績 request.setAttribute("score", 89); %> <!-- 判斷學生成績,輸出成績所對應的ABCD --> <s:if test="#request.score>90"> 優秀 </s:if> <s:elseif test="#request.score>80"> 良好 </s:elseif> <s:else> 通常 </s:else>
iterator
<s:iterator value="customers"> <%--s:iterator是struts2的一個迭代標籤,它的value屬性取值是一個OGNL表達式 var屬性:它的取值就是一個普通的字符串. 用了var:把每次遍歷的對象做爲value,把var的值做爲key,存入ContextMap中 沒用var:把每次遍歷的對象壓入棧頂,再下次遍歷以前彈棧(從棧頂移走)。 begin:開始遍歷的索引 end:遍歷的結束索引 step:遍歷的步長。 status:計數器對象 count 已經遍歷的集合元素個數 index 當前遍歷元素的索引值 odd 是否奇數行 even 是否偶數行 first 是否第一行 last 是否最後一行 --%> <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"> <TD><s:property value="custName"/></TD> <TD><s:property value="custLevel"/></TD> <TD><s:property value="custSource"/></TD> <TD><s:property value="custIndustry"/</TD> <TD><s:property value="custAddress"/></TD> <TD><s:property value="custPhone"/></TD> </TR> </s:iterator>
property
id:可選屬性,指定該元素的標識。
default:可選屬性,若是要輸出的屬性值爲null,則顯示default屬性的指定值。
escape:可選屬性,指定是否忽略HTML代碼。
value:可選屬性,指定須要輸出的屬性值,若是沒有指定該屬性,則默認輸出ValueStack棧頂的值
<%-- 輸出值棧中的值 --%> <s:property value="custName"/>
a
<%--使用struts2的超連接標籤發送請求: <s:a>鏈接內容</s:a> 屬性: href:指定url路徑 action:請求的動做名稱(類名) namespace:動做名稱所在的名稱空間 id:指定id method:指定Action調用方法 --%> <s:a action="addUIUser" namespace="/user">添加用戶</s:a> <s:a action="editUIUser" namespace="/user"> 編輯用戶 <s:param name="userid" value="%{'1'}"></s:param> </s:a> <a href="${pageContext.request.contextPath}/user/editUIUser.action?userid=1">原始超連接標籤-編輯用戶</a>
debug
debug標籤用於調試Struts2,使用它會在頁面中生成一個debug標籤,點擊後會顯示服務器各類對象信息,包括值棧、ContextMap等。
<s:debug/>
date
<%--s:date標籤的使用: 它是用於格式化輸出日期 name屬性:取值是一個ognl表達式,表示要格式化的日期對象 format屬性:指定格式 var屬性:取值是一個普通的字符串。 把格式化好的日期字符串做爲value,把var的取值做爲key。存入contextMap中 --%> <% request.setAttribute("myDate",new Date()); /* SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日"); String date = format.format(new Date()); out.println(date); */ %> ${requestScope.myDate}<br/> <s:property value="#request.myDate"/> <s:date name="#request.myDate" format="yyyy年MM月dd日" var="sdate"/> <br> 格式化後的日期:<s:property value="#sdate"/> <br/> ${sdate}
url
<%-- url標籤 做用:用於存放一個路徑 屬性: action:動做名稱 namespace:名稱空間 var:取值是一個普通字符串。他會把action和namespace組成一個url做爲value,把var的取值做爲一個key,存入contextMap中 --%> <s:url action="addUIUser" namespace="/user" var="myurl"/> <a href="<s:property value='#myurl'/>">添加用戶——url</a>
表單標籤
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>註冊界面</title> </head> <body> <s:form action="register" namespace=""> <s:textfield name="username" label="用戶名" key="Switch"/> <s:password name="password" label="密碼"/> <s:radio name="gender" list="#{'0':'男','1':'女'}" label="性別" value="0" /> <s:textfield name="age" label="年齡"/> <s:select name="city" list="#{'bj':'北京','sh':'上海','gz':'廣州','sz':'深圳'}" label="城市" headerKey="-1" headerValue="---請選擇城市---" emptyOption="true"/> <s:checkboxlist name="hibbies" list="#{'code':'寫代碼','algorithm':'算法','movie':'電影'}" label="愛好"/> <s:checkbox name="married" label="是否已婚" value="true" labelposition="left"/> <s:textarea name="description" label="自我介紹" rows="5" cols="20"/> <s:file name="phone" label="頭像"/> <s:submit value="提交"/> <s:reset value="重置"/> </s:form> </body> </html>