好久沒有作web項目了,最近公司要作個產品,目前正在作demo,暫時從大數據迴歸到web開發了,發現好多東西都忘光了,並且如今的web開發也比我作web的時候先進了許多,不少技術如雨後春筍般冒了出來,目前也在一點點的學習,在這以前我仍是先回顧一下之前的知識點吧,畢竟過久沒用真的生疏了,致使犯了不少低級錯誤,爲了之後少犯這種錯,寫幾篇小文章,梳理一下知識點。html
言歸正傳,此次回顧的是struts2攔截器。固然如今web技術已經基本不用struts了,這裏介紹仍是但願能多多關注攔截器自己。因此首先引出幾個名詞。前端
攔截器
顧名思義,攔截器就是用來攔截的一個組件,在struts中攔截的訪問action的請求。簡單的說,在訪問action以前,都會調用這個組件。利用這個特性,咱們能夠在攔截器中作不少事情,好比常說的表單校驗,登陸驗證等。java
攔截器符合DRY(don’t repeat yourself)規則。早期的開發,因爲經驗缺少等各類緣由,開發人員常常會在不少不少不一樣的地方調用一樣的方法,大部分人都是粘貼複製,這會對後期的維護工做帶來巨大的隱患。而攔截器能夠理解爲調用方法的一種改進,由於攔截器能夠在目標對象執行之前由系統自動執行,而調用方法則必須顯示的調用才能夠。這就使攔截器自己擁有更高層次的解耦性。web
攔截器棧
攔截器棧就是將攔截器按照必定的順序鏈接在一塊兒的鏈,當知足攔截的要求時,則會按照實現聲明的順序依次執行攔截器。這使得咱們能夠處理較爲複雜的狀況。ajax
瞭解了這幾個概念後,咱們回顧一下在項目中如何使用攔截器,這裏要展示的是自定義攔截器,通常真正的項目都會有本身特定的需求,不多用到struts自帶或者默認的攔截器。apache
首先,如今struts.xml中配置攔截器json
<package name="Global" extends="struts-default"> <interceptors> <!-- 定義攔截器 --> <interceptor name="loginInterceptor" class="commons.util.LoginInterceptor"></interceptor> <!-- 定義攔截器棧 --> <interceptor-stack name="CENNAVIStack"> <!-- 引用攔截器,在棧中,攔截器的前後順序決定執行的順序 --> <interceptor-ref name="loginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <!-- 將此攔截器棧設置成package全局攔截器,請求在此package下定義的action都會被攔截 --> <default-interceptor-ref name="CENNAVIStack"></default-interceptor-ref> <!-- package全局result(global-results),若是action返回的string在本身的result中沒有找到,就會查找這個全局的 --> <global-results> <result name="login" type="redirect">login.html</result> </global-results> </package> <package name="Global-json" extends="json-default"> <interceptors> <interceptor name="loginInterceptor" class="commons.util.LoginInterceptor"></interceptor> <interceptor-stack name="PBSStack"> <interceptor-ref name="loginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="PBSStack"></default-interceptor-ref> </package>
上面的配置均有註釋,這裏不細說,但要簡單解釋一下一個概念session
package
從語義上講,其實表明了每個獨立的模塊。在這個模塊中,你能夠定義隸屬於這個模塊的行爲方式,而與其餘的模塊沒有關係。因此,每一個package都有獨立的interceptor、result-type和action的定義。ide
name屬性的值的package的名字,extends的值說明了繼承哪一個包學習
其實能夠把它看做爲一個普通的java類的構造器,你所定義的攔截器、action,等等都是它的屬性。而name就是這個類的對象名,extends就至關於這個類繼承了哪一個類。這樣攔截器等等是這個對象的特有的屬性,跟其餘對象無關。
再來看struts-default和json-default
struts-default
struts-default是struts-default.xml中定義的,而咱們通常的配置文件都會繼承這個配置文件。
就攔截器而言,struts-default 包中預約義了不少攔截器,咱們繼承了這個包也就可使用其中的攔截器。固然這個包中也定義了攔截器棧(interceptor-stack)以及默認使用的攔截器棧,默認使用的攔截器棧是defaultStack,內含18個順序排列的攔截器。所以,若是自定義的package繼承了struts-default而又沒有任何攔截器上的修改,該自定義package使用的攔截器棧就是defaultStack。因此通常狀況而言都會繼承這個包。
json-default
struts2的json plugin能夠實現struts2和json的完美結合,當咱們要使用json 的時候就可使用這個包。若是繼承了這個包而且配置<result> 標籤,如
<result type="json"> <param name="root">list</param> </result>
並且在action中return了list,那麼struts就能夠將list這個對象自動轉換爲json格式數據,並返回給前端UI,不用咱們再本身寫轉換了,極大程度的方便了開發。
對於package,咱們應該靈活運用,好比定義多個package,配置不一樣的攔截器,攔截特定的action,來達到特定的目的,好比權限和功能的控制等。
上面配置配置了自定義的攔截器,接下來看看這個自定義攔截器如何寫:
package commons.util; import java.io.PrintWriter; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; import org.apache.struts2.ServletActionContext; import com.cennavi.sys.hbm.User; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; /** * * @ClassName: LoginInterceptor * @Description: TODO(這裏用一句話描述這個類的做用) * @author lzz * @date 2017年3月1日 下午4:05:53 * */ public class LoginInterceptor extends AbstractInterceptor { @Override public void init(){ //應用啓動的時候會先調用init方法 System.out.println("init"); } private static final long serialVersionUID = 2000108379092059226L; public String intercept(ActionInvocation invocation) throws Exception{ System.out.println("intercept=================="); Map session = ActionContext.getContext().getSession(); HttpServletRequest request = ServletActionContext.getRequest(); if(request.getRequestURI().indexOf(Commons.LOGIN_ACTION_URL) >= 1){ return invocation.invoke(); } User user = (User)session.get(Commons.USER_INFO); if(user != null) { return invocation.invoke(); } return Action.LOGIN; } }
上面代碼只是一個示例,真正的系統中會有較多的邏輯,好比會有對ajax請求的處理等等。
上面代碼的功能是先判斷是否是訪問的登陸的url,若是是則不攔截,直接調用登陸url中的訪問的action,若是不是登陸的url,則獲取session中的user,若是不爲空,證實在登陸的時候已經將這個user存放在session中,能夠操做,若是爲空,則須要從新登陸。其中Action.LOGIN所對應的字符串是「login」,以前咱們在struts.xml中有配置
<global-results> <result name="login" type="redirect">login.html</result> </global-results>
Action.LOGIN所對應的就是這個配置,一但攔截器返回login,則重定向login.html
固然在這個攔截器中還能夠作其餘的事情,好比權限的進一步驗證等,看我的需求。
到這,基本上把攔截器的知識簡單的回顧了。