一,拦截器的生命周期
项目启动:创建拦截器对象->调用init方法
访问:创建action对象->执行拦截器intercept方法(放行之前)->放行(actionInvocation.invoke();
)->执行antion业务方法
1)先构造拦截器对象还是Action对象:拦截器
2)先走拦截器的intercept业务方法,再走Action的业务方法
二,拦截器范围
1)局部使用
<package name="intercepter" extends="struts-default">
<!--定义拦截器-->
<interceptors>
<interceptor name="inter1" class="study.intercepter.MyIntercepter"></interceptor>
</interceptors>
<action name="user" class="study.intercepter.UserAction" method="login">
<!--使用自定义局部拦截器-->
<!--<interceptor-ref name="inter1"></interceptor-ref>-->
<result name="success" type="dispatcher">/index.jsp</result>
</action>
</package>
2)全局使用
1>不使用拦截器栈(会覆盖父包(struts-default)的全部拦截器使其失效)
<package name="intercepter" extends="struts-default">
<!--定义拦截器-->
<interceptors>
<interceptor name="inter1" class="study.intercepter.MyIntercepter"></interceptor>
</interceptors>
<!--定义全局拦截器-->
<default-interceptor-ref name="inter1"></default-interceptor-ref>
<action name="user" class="study.intercepter.UserAction" method="login">
<result name="success" type="dispatcher">/index.jsp</result>
</action>
</package>
2>使用拦截器栈(把父包的18个拦截器加进去就解决了覆盖问题)
<!--定义拦截器-->
<interceptors>
<interceptor name="inter1" class="study.intercepter.MyIntercepter"></interceptor>
<interceptor name="inter2" class="study.intercepter.MyIntercepter2"></interceptor>
<!--定义拦截器栈-->
<interceptor-stack name="mystack">
<interceptor-ref name="inter1"></interceptor-ref>
<interceptor-ref name="inter2"></interceptor-ref>
<!--这里把父包默认的18个拦截器加进去-->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
拦截器栈中拦截器执行顺序
启动时:按照栈中声明顺序执行
调用antion 时:放行前按启动循序执行拦截器->放行后先执行Action中业务方法->然后反过来执行拦截器中放行后的代码
三,值栈
1)ognl表达式
ognl表达式是struts默认使用的表达式语言
2)ognl和el的区别
ognl表达式:获取域对象数据,可以存放数据,可以调用方法
el表达式:获取域对象数据,不能存放数据,不能调用方法
3)ognl表达式核心(OgnlContext对象)
ognlContext存取数据
public class OgnlDemo1 {
//往根对象存数据
@Test
public void test2(){
User user=new User();
user.setUsername("tom");
user.setPassword("123");
try {
//创建ognlcontext对象
OgnlContext ognlContext=new OgnlContext();
ognlContext.setRoot(user);
//使用ognl表达式从OgnlContext中取数据,如果是根对象,不用带上#和对象名
Object object=Ognl.parseExpression("username");
String name=(String )Ognl.getValue(object,ognlContext,ognlContext.getRoot());
System.out.println(name);
} catch (OgnlException e) {
e.printStackTrace();
}
}
//往非根对象存数据
@Test
public void test1(){
User user=new User();
user.setUsername("tom");
user.setPassword("123");
try {
//创建ognlcontext对象
OgnlContext ognlContext=new OgnlContext();
ognlContext.put("user",user);
//使用ognl表达式从OgnlContext中取数据,如果是非根对象,必须带上#
Object object=Ognl.parseExpression("#user.username");
String name=(String )Ognl.getValue(object,ognlContext,ognlContext.getRoot());
System.out.println(name);
} catch (OgnlException e) {
e.printStackTrace();
}
}
4)struts2的值栈(ValueStack)对象(利用OgnlContext对象)
ValueStack是接口,真正的实现对象是OgnlValueStack
1>valueStack的数据存储结构:分为List(根)栈 和 map(非根)栈
list栈:主要存放action对象和provider代理对象
map栈:存放各个域存放的数据和用户的参数信息
public class OgnlDemo2 {
@Test
public void test(){
//获取ActionContext对象
ActionContext actionContext=ActionContext.getContext();
//往域对象存放数据
actionContext.getContextMap().put("hello","hello");
actionContext.getSession().put("hi","hi");
actionContext.getApplication().put("sawadika","sawadika");
//从antionContext中获取OgnlValueStack对象
ValueStack valueStack=actionContext.getValueStack();
//往valueStack的根对象(list栈)中存放数据
valueStack.push("heiheihei");
}
}
5)页面获取值栈valueStack数据
List栈的数据(不需要#号,不需要key)
输入Ognl: user
作用: 直接到List栈的每个对象去搜索对应的属性。
搜索规则:
从List栈的栈顶开始搜素 -> user -> 返回,找不到继续向下找
栈的第二个元素 -> user -> 返回,找不到继续向下找
… -> user - > 空
注意:在List栈中尽量不要在两个栈对象中出现相应的属性名,如果出现相应的属性名,只获取第一个对象的属性。
jsp页面取数据时需要<%@ taglib prefix="s" uri="/struts-tags" %>
标签
<body>
<%--查看值栈所有数据--%>
<s:debug></s:debug>
<%--取出list栈中的数据s:property可以支持ognl表达式--%>
<s:property value="user.name"/>
<%--user对象嵌套book对象--%>
<s:property value="user.book.id"/>
<%--去除map栈中的数据--%>
<%--对于request域可以忽略#request直接去对象,因为值栈对象是通过request域传递到页面的--%>
<s:property value="#request.user.name"/>
<s:property value="user.name"/>
<s:property value="#session.user.name"/>
<s:property value="#application.user.name"/>
<%--#attr类似于findAttribute依次从小到大三个域中取对象--%>
<s:property value="#attr.user"/>
<%--#parameters是获取的参数(url中携带的才叫参数,user是属性不是参数)--%>
<s:property value="#parameters.name"/>
</body>