- 攔截器
1.1 概述
基本概念
Intercetor, 即爲攔截器。
1) 在Struts2中,把每一個功能都用一個個的攔截器實現;用戶想用struts的哪個功能的時候,可以自由組裝使用。
2)Struts2中,爲了方法用戶對攔截器的引用,提供了攔截器棧的定義,裏面可以包含多個攔截器。 文件夾(文件, 文件2) 攔截器棧(攔截器,攔截器2)
3)Struts2中,如果用戶沒有指定執行哪些攔截器,struts2有一個默認執行的棧,defaultStack;
一旦如果用戶有指定執行哪些攔截器,默認的攔截器棧就不會被執行
攔截器的設計,就是基於組件設計的應用!
攔截器配置舉例
struts-default.xml文件中,定義了struts提供的所有攔截器!
//1. 定義攔截器以及攔截器棧
<interceptors>
1.1 攔截器定義
<interceptor name="" class="" />
1.2 攔截器棧的定義
<interceptor-stack name="defaultStack">
引用了上面攔截器(1.1)
</interceptor-stack>
</interceptors>
- 默認執行的攔截器(棧)
<default-interceptor-ref name="defaultStack"/>
API
|– Interceptor 攔截器接口
|– AbstractInterceptor 攔截器默認實現的抽象類; 一般用戶只需要繼承此類即可繼續攔截器開發
|– ActionInvocation 攔截器的執行狀態,調用下一個攔截器或Action
攔截器與過濾器區別:
….
1.2 自定義一個攔截器案例
步驟:
1. 寫攔截器類 (看生命週期)
2. 配置
/**
* 自定義攔截器
*
*/
public class HelloInterceptor implements Interceptor{
// 啓動時候執行
public HelloInterceptor(){
System.out.println("創建了攔截器對象");
}
// 啓動時候執行
@Override
public void init() {
System.out.println("執行了攔截器的初始化方法");
}
// 攔截器業務處理方法 (在訪問action時候執行? 在execute之前執行?)
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("2. 攔截器,業務處理-開始");
// 調用下一個攔截器或執行Action (相當於chain.doFilter(..)
// 獲取的是: execute方法的返回值
String resultFlag = invocation.invoke();
System.out.println("4. 攔截器,業務處理-結束");
return resultFlag;
}
@Override
public void destroy() {
System.out.println("銷燬....");
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="hello" extends="struts-default">
<!-- 【攔截器配置】 -->
<interceptors>
<!-- 配置用戶自定義的攔截器 -->
<interceptor name="helloInterceptor" class="cn.itcast.a_interceptor.HelloInterceptor"></interceptor>
<!-- 自定義一個棧: 要引用默認棧、自定義的攔截器 -->
<interceptor-stack name="helloStack">
<!-- 引用默認棧 (一定要放到第一行)-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 引用自定義攔截器 -->
<interceptor-ref name="helloInterceptor"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 【執行攔截器】 -->
<default-interceptor-ref name="helloStack"></default-interceptor-ref>
<!-- Action配置 -->
<action name="hello" class="cn.itcast.a_interceptor.HelloAction">
<result name="success"></result>
</action>
</package>
</struts>
1.2 攔截器執行流程
UML (時序圖)
啓動:
創建所有攔截器、執行init()
訪問:
先創建Action,
再執行攔截器,
最後:攔截器放行,執行execute();
1.3 攔截器案例
需求:
登陸後,顯示列表!
案例準備:
Struts jar文件
DbUtils組件
數據庫連接池/ 驅動包
–> login.jsp
<body>
<form method="post" action="${pageContext.request.contextPath }/user_login.action">
用戶名:<input type="text" name="admin.userName"><br/>
密碼:<input type="text" name="admin.pwd"><br/>
<input type="submit" value="登陸"><br/>
</form>
</body>
UserAction.java
public class UserAction extends ActionSupport {
// ---------1. 封裝請求數據-----------
private Admin admin;
public Admin getAdmin() {
return admin;
}
public void setAdmin(Admin admin) {
this.admin = admin;
}
// ---------2. 調用的Service-----------
private AdminService adminService = new AdminService();
// 登陸
public String login() {
try {
Admin userInfo = adminService.login(admin);
// 判斷
if (userInfo == null){
// 登陸失敗
return "input";
}
// 登陸成功:數據保存在session中
ActionContext.getContext().getSession().put("userInfo", userInfo);
// 登陸成功
return "loginSuccess";
} catch (Exception e) {
return ERROR;
}
}
// 列表
public String list() {
try {
// 查詢全部
List<Admin> list = adminService.getAll();
// 保存到request
ActionContext.getContext().getContextMap().put("listAdmin", list);
return "list";
} catch (Exception e) {
return ERROR;
}
}
public String add() {
return null;
}
}
list.jsp
<body>
<h1>歡迎你,${userInfo.userName }</h1>
<table align="center" border="1">
<tr>
<td>序號</td>
<td>編號</td>
<td>用戶名</td>
<td>密碼</td>
</tr>
<%--@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" --%>
<!-- 用struts標籤迭代數據 -->
<%@taglib uri="/struts-tags" prefix="s" %>
<s:iterator var="admin" value="#request.listAdmin" status="st">
<tr>
<td>
<s:property value="#st.count"/>
</td>
<td>
<s:property value="#admin.id"/>
</td>
<td>
<s:property value="#admin.userName"/>
</td>
<td>
<s:property value="#admin.pwd"/>
</td>
</tr>
</s:iterator>
</table>
</body>
自定義攔截器
public class UserCheckInterceptor extends AbstractInterceptor{
/**
* 攔截器業務處理方法
*/
public String intercept(ActionInvocation invocation) throws Exception {
// 拿到當前執行的方法名:判斷,只有當前方法名不是login,就進行驗證
// 獲取ActionContext對象
ActionContext ac = invocation.getInvocationContext();
// 獲取action的代理對象
ActionProxy proxy = invocation.getProxy();
// 獲取當前執行的方法名
String methodName = proxy.getMethod();
// 判斷
if (!"login".equals(methodName)) {
// 先獲取當前登陸的用戶
Object obj = ac.getSession().get("userInfo");
if (obj == null) {
// 沒有登陸
return "input";
} else {
// 當前用戶有登陸
return invocation.invoke();
}
} else {
// 說明當前用戶正在登陸
return invocation.invoke();
}
}
}
配置攔截器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="user" extends="struts-default">
<!-- 【攔截器配置】 -->
<interceptors>
<interceptor name="loginCheck" class="cn.itcast.interceptor.UserCheckInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 【執行攔截器:第一種寫法: 當前包下所有的acntion都執行myStack棧】
<default-interceptor-ref name="myStack"></default-interceptor-ref>
-->
<!-- 全局配置 -->
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
<!--第二種寫法: 只是在這一個Action中執行myStack棧
<interceptor-ref name="defaultStackt"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
-->
<!-- 第三種寫法:執行用戶棧(與第二種寫法一樣, 只在當前aciton中執行自定義棧) -->
<interceptor-ref name="myStack"></interceptor-ref>
<!-- 1. 登陸失敗 -->
<result name="input">/login.jsp</result>
<!-- 2. 登陸成功 -->
<result name="loginSuccess" type="redirectAction">user_list</result>
<!-- 3. 列表展示 -->
<result name="list">/WEB-INF/list.jsp</result>
</action>
</package>
</struts>