※系統內鍵的攔截器
HelloInterceptor.javapublic class HelloInterceptor extends ActionSupport{ public void Hello(){ System.out.println("Hello Interceptor!"); } }和一般action一樣
struts.xml
<action name="hello" class="action.HelloInterceptor"> <interceptor-ref name="timer" /> </action>因為package有extends="struts-default",這個檔案在struts2-core-2.x.x.jar裡, 所以name可以是timer,還有很多,可以參考這裡
測試時,在瀏覽器的網址列最後打上hello!Hello.action, 記得struts.xml要加上<constant name="struts.enable.DynamicMethodInvocation" value="true" />
※自訂攔截器
TestInterceptor.javapublic class TestInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("攔截成功!"); return invocation.invoke(); } }繼承一個叫AbstractInterceptor的抽象類別,並覆寫方法,invocation.invoke()表示繼續執行
struts.xml
<interceptors> <interceptor name="testICR" class="interceptor.TestInterceptor" /> </interceptors> <action name="hello" class="action.HelloInterceptor"> <interceptor-ref name="timer" /> <interceptor-ref name="testICR" /> </action>可以有很多攔截器,這個例子有兩個,要注意interceptors要寫在action上面,錯誤會有提示
※多個攔截器設定
也就是上面的struts.xml可以改成以下的寫法<interceptors> <!-- interceptor可以很多 --> <interceptor name="testICR" class="interceptor.TestInterceptor" /> <interceptor-stack name="xxx"> <interceptor-ref name="timer" /> <interceptor-ref name="testICR" /> </interceptor-stack> </interceptors> <action name="hello" class="action.HelloInterceptor"> <interceptor-ref name="xxx" /> </action>把interceptor-ref搬上去後,用interceptor-stack包起來,然後取個名字,下面就使用新的名字即可
※全域攔截器設定
<interceptors> <interceptor name="testICR" class="interceptor.TestInterceptor" /> <interceptor-stack name="xxx"> <interceptor-ref name="timer" /> <interceptor-ref name="testICR" /> </interceptor-stack> <default-interceptor-ref name="xxx" /> </interceptors> <action name="hello1" class="action.HelloInterceptor1" /> <action name="hello2" class="action.HelloInterceptor2" /> <action name="hello3" class="action.HelloInterceptor3" />default-interceptor-ref設定完,所有的actin在執行之前都會攔截
※defaultStack
攔截器有個defaultStack,主要是執行struts2的方法<interceptor-ref name="defaultStack" />不加時,會執行setContainer()-->execute()
加上後,會執行setContainer()-->validate()-->hasErrors()-->execute()
所以如果想用validate方法,就要設這一行
※模擬一個登入攔截
登入時,如果帳號或密碼沒輸入,就再原網頁不動login.jsp
<form action="login.action" method="post"> <input type="text" name="user.userName" /><br /> <input type="password" name="user.userPassword" /><br /> <input type="reset" /> <input type="submit" /> </form>
struts.xml
<interceptors> <interceptor name="login" class="interceptor.LoginInterceptor" /> <interceptor-stack name="stack"> <interceptor-ref name="login" /> </interceptor-stack> </interceptors> <action name="login" class="login.LoginAction" method="execute"> <interceptor-ref name="stack" /> <result name="login">/struts2/login.jsp</result> <!-- 方法一 --> <result name="success">/struts2/success.jsp</result> <!-- 方法二,只是測試redirectAction --> <result name="success" type="redirectAction">xxx.action</result> </action> <!-- 此action方法二才需要 --> <action name="xxx" class="login.LoginAction" method="success"> <result name="success">/struts2/success.jsp</result> </action>
LoginInterceptor.java的intercept
HttpServletRequest req = ServletActionContext.getRequest(); User user = new User(); user.setUserName(req.getParameter("user.userName")); user.setUserPassword(req.getParameter("user.userPassword")); // 方法一 Map<String, Object> map = invocation.getInvocationContext() .getSession(); // 方法二 // Map<String, Object> map = ActionContext.getContext().getSession(); if (user.getUserName().isEmpty() || user.getUserPassword().isEmpty()) { //方法一 HttpServletResponse res = ServletActionContext.getResponse(); res.sendRedirect("/Struts2Demo/struts2/login.jsp"); return null; //方法二 // return ActionSupport.LOGIN; } else { map.put("user", user); return invocation.invoke(); }
LoginAction.java,記得繼承ActionSupport
private User user; //setter/getter @Override public String execute() throws Exception { return SUCCESS; } //此方法為struts.xml的方法二才需要 public String success() { return SUCCESS; }
User.java
private String userName; private String userPassword; //setter/getter
success.jsp
<%@ taglib prefix="s" uri="/struts-tags"%> <%@ page isELIgnored="false"%> OGNL: <ul> <li>帳號:<s:property value="#session.user.userName"/> <li>密碼:<s:property value="#session.user.userPassword"/> </ul> EL: <ul> <li>帳號:${user.userName} <li>密碼:${user.userPassword} </ul>
※用攔截器防止頁面重覆提交
以登入的例子修改struts.xml<constant name="struts.custom.i18n.resources" value="Message" /> <interceptors> <interceptor name="login" class="interceptor.LoginInterceptor" /> <interceptor-stack name="stack"> <interceptor-ref name="login" /> <interceptor-ref name="basicStack" /> <interceptor-ref name="token" /> </interceptor-stack> </interceptors> <action name="login" class="login.LoginAction" method="execute"> <interceptor-ref name="stack" /> <result name="login">/struts2/login.jsp</result> <result name="success">/struts2/success.jsp</result> <result name="invalid.token">/struts2/login.jsp</result> </action>注意invalid.token要設定
login.jsp增加兩行
<form action="login.action" method="post"> <s:token name="ooo" /> <s:actionerror /> <input type="text" name="user.userName" /><br /> <input type="password" name="user.userPassword" /><br /> <input type="reset" /> <input type="submit" /> </form>s:token的name可以隨便打,網頁原始碼可看出會變成兩行hidden
s:actionerror為針測到重覆提交時所產生的訊息
Message.properties 訊息定義在這個檔裡,struts.xml要設定這個檔名
struts.messages.invalid.token=\u8868\u55AE\u91CD\u8986\u63D0\u4EA4\uFF01
可參考這裡
如果把jsp的s:token放在form外面,不用重覆提交,一次就出現Message.properties的訊息了,而且在控制台會出「Could not find token name in params.」的錯