攔截器
-
攔截器概述 :
- 基本概念 : Intercetor, 即為攔截器僚焦。
- 在Struts2中把每一個功能都用一個個的攔截器實(shí)現(xiàn)助隧;用戶想用struts的哪個功能的時候,可以自由組裝使用。
- Struts2中為了方法用戶對攔截器的引用, 提供了攔截器棧的定義, 里面可以包含多個攔截器查辩。文件夾(文件, 文件2) 攔截器棧(攔截器, 攔截器2)
- Struts2中如果用戶沒有指定執(zhí)行哪些攔截器, struts2有一個默認(rèn)執(zhí)行的棧, defaultStack; 一旦如果用戶有指定執(zhí)行哪些攔截器, 默認(rèn)的攔截器棧就不會被執(zhí)行攔截器的設(shè)計(jì), 就是基于組件設(shè)計(jì)的應(yīng)用胖笛!
- 基本概念 : Intercetor, 即為攔截器僚焦。
攔截器配置舉例 : struts-default.xml文件中,定義了struts提供的所有攔截器
// 1. 定義攔截器以及攔截器棧
<interceptors>
// 1.1 攔截器定義
<interceptor name="" class="" />
// 1.2 攔截器棧的定義
<interceptor-stack name="defaultStack">
引用了上面攔截器(1.1)
</interceptor-stack>
</interceptors>
// 2. 默認(rèn)執(zhí)行的攔截器(棧)
<default-interceptor-ref name="defaultStack"/>
-
攔截器API :
- Interceptor 攔截器接口
-
AbstractInterceptor
: 攔截器默認(rèn)實(shí)現(xiàn)的抽象類; 一般用戶只需要繼承此類即可繼續(xù)攔截器開發(fā) -
ActionInvocation
: 攔截器的執(zhí)行狀態(tài), 調(diào)用下一個攔截器或Action
-
自定義一個攔截器案例
- 步驟:
- 寫攔截器類 (看生命周期)
- 配置
- 代碼示例
- 步驟:
// 自定義攔截器
public class HelloInterceptor implements Interceptor{
// 啟動時候執(zhí)行
public HelloInterceptor(){
System.out.println("創(chuàng)建了攔截器對象");
}
// 啟動時候執(zhí)行
@Override
public void init() {
System.out.println("執(zhí)行了攔截器的初始化方法");
}
// 攔截器業(yè)務(wù)處理方法 (在訪問action時候執(zhí)行宜岛? 在execute之前執(zhí)行长踊?)
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("2. 攔截器,業(yè)務(wù)處理-開始");
// 調(diào)用下一個攔截器或執(zhí)行Action (相當(dāng)于chain.doFilter(..)
// 獲取的是: execute方法的返回值
String resultFlag = invocation.invoke();
System.out.println("4. 攔截器萍倡,業(yè)務(wù)處理-結(jié)束");
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>
<!-- 自定義一個棧: 要引用默認(rèn)棧身弊、自定義的攔截器 -->
<interceptor-stack name="helloStack">
<!-- 引用默認(rèn)棧 (一定要放到第一行)-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<!-- 引用自定義攔截器 -->
<interceptor-ref name="helloInterceptor"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 【執(zhí)行攔截器】 -->
<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>
-
攔截器執(zhí)行流程
- 啟動 : 創(chuàng)建所有攔截器、執(zhí)行init()
- 訪問:
- 先創(chuàng)建Action列敲,
- 再執(zhí)行攔截器阱佛,
- 最后 : 攔截器放行,執(zhí)行execute();
-
攔截器案例
- 需求:登陸后戴而,顯示列表凑术!
- 案例準(zhǔn)備:
- Struts jar文件
- DbUtils組件
- 數(shù)據(jù)庫連接池/ 驅(qū)動包
- 代碼
- 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. 封裝請求數(shù)據(jù)-----------
private Admin admin;
public Admin getAdmin() {
return admin;
}
public void setAdmin(Admin admin) {
this.admin = admin;
}
// ---------2. 調(diào)用的Service-----------
private AdminService adminService = new AdminService();
// 登陸
public String login() {
try {
Admin userInfo = adminService.login(admin);
// 判斷
if (userInfo == null){
// 登陸失敗
return "input";
}
// 登陸成功:數(shù)據(jù)保存在session中
ActionContext.getContext().getSession().put("userInfo", userInfo);
// 登陸成功
return "loginSuccess";
} catch (Exception e) {
return ERROR;
}
}
// 列表
public String list() {
try {
// 查詢?nèi)? 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標(biāo)簽迭代數(shù)據(jù) -->
<%@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{
/**
* 攔截器業(yè)務(wù)處理方法
*/
public String intercept(ActionInvocation invocation) throws Exception {
// 拿到當(dāng)前執(zhí)行的方法名:判斷填硕,只有當(dāng)前方法名不是login,就進(jìn)行驗(yàn)證
// 獲取ActionContext對象
ActionContext ac = invocation.getInvocationContext();
// 獲取action的代理對象
ActionProxy proxy = invocation.getProxy();
// 獲取當(dāng)前執(zhí)行的方法名
String methodName = proxy.getMethod();
// 判斷
if (!"login".equals(methodName)) {
// 先獲取當(dāng)前登陸的用戶
Object obj = ac.getSession().get("userInfo");
if (obj == null) {
// 沒有登陸
return "input";
} else {
// 當(dāng)前用戶有登陸
return invocation.invoke();
}
} else {
// 說明當(dāng)前用戶正在登陸
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>
<!-- 【執(zhí)行攔截器:第一種寫法: 當(dāng)前包下所有的acntion都執(zhí)行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中執(zhí)行myStack棧
<interceptor-ref name="defaultStackt"></interceptor-ref>
<interceptor-ref name="loginCheck"></interceptor-ref>
-->
<!-- 第三種寫法:執(zhí)行用戶棧(與第二種寫法一樣, 只在當(dāng)前aciton中執(zhí)行自定義棧) -->
<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>
Structs國際化
- Struts2中國際化:
- 寫資源文件 (同servlet)
- 讀資源文件
- 程序:ResourceBundle (同servlet)
- JSP:
1)jstl標(biāo)簽(同servlet)
2)struts標(biāo)簽獲取資源文件內(nèi)容
- 具體步驟 :
- 寫資源文件 :
-
Msg.properties
: 默認(rèn)的語言環(huán)境, 找不到配置就找它 -
Msg_en_US.properties
: 美國
- 加載 :
<constant name="struts.custom.i18n.resources" value="cn.itcast.config.msg"></constant>
- 使用 : 標(biāo)簽name值直接寫配置文件中的key :
<s:text name="title"></s:text>
- 另外一點(diǎn)扁眯,(推薦)加載資源文件通過常量加載還可以在頁面加載, 這樣用:
<s:i18n name="cn.itcast.config.msg">
<s:text> 標(biāo)簽必須放到標(biāo)簽體中 </s:text>
</s:i18n>
Ognl表達(dá)式語言
-
概述 : OGNL是Object Graphic Navigation Language(對象圖導(dǎo)航語言)的縮寫, 它是一個開源項(xiàng)目, Struts2框架使用OGNL作為默認(rèn)的表達(dá)式語言
- OGNL優(yōu)勢
1壮莹、支持對象方法調(diào)用,如xxx.doSomeSpecial()姻檀;
2命满、支持類靜態(tài)的方法調(diào)用和值訪問,表達(dá)式的格式:
@[類全名(包括包路徑)]@[方法名 | 值名]绣版,例如:
@java.lang.String@format('foo %s', 'bar')
或@tutorial.MyConstant@APP_NAME胶台;
3、支持賦值操作和表達(dá)式串聯(lián)杂抽,如price=100, discount=0.8, calculatePrice()诈唬,這個表達(dá)式會返回80;
4缩麸、訪問OGNL上下文(OGNL context)和ActionContext
5铸磅、操作集合對象 - 總結(jié) : OGNL 有一個上下文(Context)概念,說白了上下文就是一個MAP結(jié)構(gòu), 它實(shí)現(xiàn)了 java.utils.Map 的接口杭朱。 OgnlContext對象
- 分析:Struts框架默認(rèn)就支持Ognl表達(dá)式語言(struts必須引用的包:ognl.jar)
- 作用 : 頁面取值用
1> El表達(dá)式語言 : jsp頁面取值的標(biāo)準(zhǔn)阅仔。(默認(rèn)直接可以使用) (應(yīng)用范圍更廣)
2> Ognl表達(dá)式語言 : struts標(biāo)簽?zāi)J(rèn)支持的表達(dá)式語言。必須配置struts標(biāo)簽用, 不能離開struts標(biāo)簽直接用
- OGNL優(yōu)勢
-
OgnlContext對象 : OgnlContext對象是ognl表達(dá)式語言的核心弧械。
- 源碼類:public class OgnlContext extends Object implements Map{..}硬編碼方式八酒,了解OgnlContext對象:
// OgnlContext用法
public class OgnlDemo1 {
/**
* 1. Ognl表達(dá)式語言取值,取非根元素的值刃唐,必須用#號
* @throws Exception
*/
@Test
public void testOgnl() throws Exception {
// 創(chuàng)建一個Ognl上下文對象
OgnlContext context = new OgnlContext();
// 放入數(shù)據(jù)
User user = new User();
user.setId(100);
user.setName("Jack");
// 【往非根元素放入數(shù)據(jù)羞迷, 取值的時候表達(dá)式要用"#"】
context.put("user", user);
// 獲取數(shù)據(jù)(map)
// 先構(gòu)建一個Ognl表達(dá)式, 再解析表達(dá)式
Object ognl = Ognl.parseExpression("#user.name");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
/**
* 2. Ognl表達(dá)式語言語言取值界轩,取根元素的值,不用帶#號
* @throws Exception
*/
@Test
public void testOgn2() throws Exception {
// 創(chuàng)建一個Ognl上下文對象
OgnlContext context = new OgnlContext();
// 放入數(shù)據(jù)
User user = new User();
user.setId(100);
user.setName("Jack");
// 【往根元素放入數(shù)據(jù)】
context.setRoot(user);
// 獲取數(shù)據(jù)(map)
// 先構(gòu)建一個Ognl表達(dá)式, 再解析表達(dá)式
Object ognl = Ognl.parseExpression("address.province");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
/**
* 3.Ognl對 靜態(tài)方法調(diào)用的支持
* @throws Exception
*/
@Test
public void testOgn3() throws Exception {
// 創(chuàng)建一個Ognl上下文對象
OgnlContext context = new OgnlContext();
// Ognl表單式語言闭树,調(diào)用類的靜態(tài)方法
//Object ognl = Ognl.parseExpression("@Math@floor(10.9)");
// 由于Math類在開發(fā)中比較常用耸棒,所以也可以這樣寫
Object ognl = Ognl.parseExpression("@@floor(10.9)");
Object value = Ognl.getValue(ognl, context, context.getRoot());
System.out.println(value);
}
}
- ValueStack(即值棧對象) :
- 值棧對象:是整個struts數(shù)據(jù)存儲的核心,或者叫中轉(zhuǎn)站报辱。用戶每次訪問struts的action,都會創(chuàng)建一個Action對象单山、值棧對象碍现、ActionContext對象; 然后把Action對象放入值棧中米奸; 最后再把值棧對象放入request中昼接,傳入jsp頁面(key: struts.valueStack); 開發(fā)者只需要通過ActionContext對象就可以訪問struts的其他的關(guān)鍵對象(ActionContext是給開發(fā)者用的,便于學(xué)習(xí)與使用)
- 問題 : OgnlContext與ValueStack對象的關(guān)系悴晰?
- Struts標(biāo)簽 : Struts標(biāo)簽取值慢睡,就使用了Ognl表達(dá)式語言