要部署struts2 framework我們必須在web.xml中加入這段
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>當 FilterDispatcher 根據 action name 所對應到 struts.xml 中的 Action class 之後,
Struts2 核心會先呼叫 Interceptor Stack 中的所有 interceptors。
接著再呼叫 Action class 中的 execute() method,完成後再呼叫 Result 幫助我們排版,
這過程中都會使用到 OGNL 到 ValueStack 中幫助我們取得必要的資料。
Interceptor Stack
這裡我們先將重點擺在Interceptor。Interceptor Stack 是在整個流程中第一個被呼叫的,
也是最後一個被呼叫的。Interceptor Stack 中包含一集合的 interceptors,
而 interceptors 的排列方式是以 stack 的方式排列。
下面我們先寫一個簡單無牽扯自訂interceptor的範例。
首先我們先新增一個Login.jsp頁面。
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>login</title> </head> <body> <s:form action="/example/Hello" method="post"> <s:textfield name="user_name" label="User Name:"/> <s:submit/> </s:form> </body> </html>這個頁面會呼叫hello action,所以我們接下來編寫一個HelloWorld.java來處理這個呼叫。
package example; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.StrutsStatics; public class HelloWorld extends ActionSupport { private String user_name; private String message; @Override public String execute() throws Exception { message = "Hello:" + user_name; return SUCCESS; } public String getUser_name() { return user_name; } public void setUser_name(String user_name) { this.user_name = user_name; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }hello action被呼叫時會自動執行excute這個method,當處理完後會藉由return "String"告訴
framework要將結果導向那個result頁面。
接下來我們再編寫一個HellowWorld.jsp來作為輸出頁面。
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hello World</title> </head> <body> <h2><s:property value="message"/></h2> </body> </html>
至於如何將Login.jsp與HelloWorld.java做連結以及利用result標韱來控制輸出頁面呢?
則是在struts.xml中設定。
<struts> <package name="example" namespace="/example" extends="struts-default"> <action name="Hello" class="example.HelloWorld"> <result name="success">/example/HelloWorld.jsp</result> <result name="login">/example/LOGIN.jsp</result> </action> </package> </struts>上述例子表示,
當action return "success"時會導向HelloWorld.jsp,
當return "login"時會導向Login.jsp。
這裡有兩個需要注意的地方:
1.在jsp頁面中呼叫action時,必須加入其package的namespace為prefix,
如action="/example/Hello";
2.result的name屬性值是有區分大小寫的。
下面為這個範例的執行結果:
輸入名稱後
會出現歡迎頁面
接下來進入這篇的重點,我們要在這個流程中加入自訂的interceptor,
編寫一個AuthorizationInterceptor.java,
自訂的interceptor須繼承AbstractInterceptor介面。
package example; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class AuthorizationInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation ai) throws Exception { return ai.invoke(); } }當interceptor發生作用時會呼叫intercept這個method。
而利用ActionInvocation的getInvocationContext()method,
我們可以得到儲存全文流程資料的ActionContext物件,這時就可以自由發揮了。
回頭看第一張framework流程圖,interceptor可以invoke原本request呼叫的action,
也可以直接return result頁面,
在這個例子中我們在interceptor中不做任何事,直接invoke action。
要讓自訂的interceptor發揮作用還需要在struts.xml中加以指明。
<struts> <package name="example" namespace="/example" extends="struts-default"> <interceptors> <interceptor name ="auth" class ="example.AuthorizationInterceptor"/> </interceptors> <action name="Hello" class="example.HelloWorld"> <interceptor-ref name ="auth"/> <result name="success">/example/HelloWorld.jsp</result> <result name="login">/example/LOGIN.jsp</result> </action> </package> </struts>表示呼叫hello action時必須先經過auth這個interceptor。
我們再一次的執行這個範例,確發現了意外的結果。
Login.jsp所輸入的使用者名稱無法帶到所呼叫的hello action,導致HelloWorld.jsp
頁面輸出時user_name欄位值為null。
這個原因是因為當我們自訂的interceptor呼叫invoke method時,整個flow會回到
framework的開頭階段,此時hello action並非由Login.jsp直接呼叫,
導致Login.jsp中的textfield欄位自動調用HellowWorld.java中的setUser_name()的機制失效。
此時hello action(HelloWorld.java)就必須自行由request中取出Login.jsp傳來的parameter。
將HellowWorld.java的execute method內容改寫如下:
導致Login.jsp中的textfield欄位自動調用HellowWorld.java中的setUser_name()的機制失效。
此時hello action(HelloWorld.java)就必須自行由request中取出Login.jsp傳來的parameter。
將HellowWorld.java的execute method內容改寫如下:
public String execute() throws Exception { ActionContext actionContext = ActionContext.getContext(); HttpServletRequest request= (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST); message = "Hello:" + request.getParameter("user_name"); return SUCCESS; }接著再一次執行修改過後的範例,就又可以看到正確的輸出結果了。
static-params interceptor 可以通過來call Action class 的相應 setter method
回覆刪除< interceptor-ref name="params"/>