※系統內鍵的攔截器
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.」的錯


