文章目录
- 1、OGNL
- 1-1 什么是ognl
- 1-2 ognl的使用要素
- 1-3 ognl入门
- 2、值栈
- 2-1 什么是值栈
- 2-2 值栈的内部结构
- 2-3 值栈与actioncontext的关系
- 2-4 获得值栈
- 2-5 操作值栈——向值栈中存入数据
- 2-6 获取值栈数据
- 3、ognl中的特殊字符
- 3-1 #号
- 3-2 %号
- 3-3 $号
- 4、struts2的拦截器(重要)
- 4-1 什么是拦截器
- 4-2 Struts2的执行流程
- 4-3 拦截器入门
- 5、struts2的标签库
- 5-1 通用标签库
- 5-2 UI标签库(方便数据回显)
1、OGNL
1-1 什么是ognl
- ognl : 调用对象的方法,获取struts2值栈的数据。ognl其实是第三方表达式语言。
1-2 ognl的使用要素
- 表达式
- 跟对象
- Context对象
1-3 ognl入门
1-3-1 ognl在Java中的入门
- 访问对象的方法
//java中使用ognl表达式
public void demo1() throws OgnlException {
OgnlContext context = new OgnlContext();
Object root = context.getRoot();
Object object = Ognl.getValue("'hello'.length()", context, root);
System.out.println(object);
}
- 访问对象的静态方法
public void demo2() throws OgnlException {
OgnlContext context = new OgnlContext();
Object root = context.getRoot();
//访问静态方法的写法
Object object = Ognl.getValue("@java.lang.Math@random()", context, root);
System.out.println(object);
}
- 获取root中的数据
- 获取context中的数据
获取context中的数据时,表达式数据名称前面要添加#
1-3-2 ognl在struts2中的环境入门
- 首先要在jsp引入struts2的包,
<%@ taglib uri="/struts-tags" prefix="s"%>
- 在jsp中使用
<s:property value=""/>
标签来使用ognl表达式- struts2中ognl访问静态方法默认是关闭的,需要在struts.xml中配置打开
加入如下代码即可打开:
<!-- 允许ognl访问静态成员 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<h1>ognl访问对象的方法</h1>
<s:property value="'hello.length()'"/>
<h1>ognl访问静态的方法</h1>
<s:property value="@java.lang.Math@random()"/>
2、值栈
2-1 什么是值栈
- ValueStack其实类似于一个数据中转站(struts2框架当中的数据都保存到了ValueStack中)
ValueStack接口,实现类ognlValueStack类
ValueStack贯穿整个Action的生命周期。(Action一旦被创建了,框架就会创建一个ValueStack对象)
2-2 值栈的内部结构
ValueStack中有两个主要的区域:
root区域:其实就是一个ArrayList。里面一般放置对象,获取root的数据不需要加#
context区域:其实就是一个Map。里面放置的是web开发的常用的对象数据的引用。获取context数据需要加#
request
session
application
parameters
attr
所说的操作值栈,通常指的是操作的ValueStack中的root区域
可以在jsp中加入标签
<s:debug></s:debug>
来查看值栈中的内容
2-3 值栈与actioncontext的关系
- ServletContext:Servlet的上下文
- ActionContext:Action的上下文
通过源码查看到,当请求过来的时候,执行过滤器中的doFilter方法,在这个方法中创建ActionContext,在创建ActionContext过程中,创建ValueStack对象,将ValueStack对象传递给ActionContext对象所以可以通过ActionContext获取值栈对象
ActionContext对象之所以能够访问Servlet的API(访问时域对象的数据)。因为在其内部有值栈的引用。
2-4 获得值栈
两种方式获得值栈
public String execute() throws Exception {
//第一种方式:通过ActionContext获取
ValueStack stack = ActionContext.getContext().getValueStack();
//第二种方式:通过request对象获取
ValueStack stack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
System.out.println(stack == stack2);
return NONE;
}
2-5 操作值栈——向值栈中存入数据
第一种方式:在Action中提供属性的get方法的方式
默认情况下,将Action对象压入到值栈,Action的数据也会在值栈中
第二种方式:使用ValueStack中本身的方法
- 第一方式(一定要写出javabean的get方法)
private User user ;
public User getUser() {
return user;
}
@Override
public String execute() throws Exception {
user = new User("狗得", "2222");
return super.execute();
}
<s:property value="user.username"/>
<s:property value="user.password"/>
- 第二种方式
首先获得到值栈,然后使用值栈的push和set方法即可向值栈中存值。
public String execute() throws Exception {
ValueStack stack = ActionContext.getContext().getValueStack();
stack.push(new User("deiB","22")); //push的方法传的是一个对象
stack.set("Customer", "黑狗向前冲"); //set的方法传的是键值对
return super.execute();
}
<s:property value="username"/>
<s:property value="password"/>
<s:property value="Customer"/>
2-6 获取值栈数据
<s:debug></s:debug>
<!-- 获取一个对象的数据 -->
<s:property value="username"/><br>
<s:property value="password"/><br><hr>
<!-- 获取集合中的数据 -->
<s:property value="list[0].username"/>
<s:property value="list[0].password"/><br>
<s:property value="list[1].username"/>
<s:property value="list[1].password"/><br>
<s:property value="list[2].username"/>
<s:property value="list[2].password"/><br>
<hr>
<!-- 获取context中的数据,需要加# -->
<s:property value="#request.username"/><br>
<s:property value="#session.username"/><br>
<s:property value="#application.username"/><br>
<s:property value="#attr.username"/><br>
<s:property value="#parameters.id"/><br><hr>
3、ognl中的特殊字符
3-1 #号
- 获取context数据
<%
request.setAttribute("deidei", "得得向前冲");
%>
<s:property value="#request.deidei"/>
- 构建一个map集合
<s:iterator value="#{'aaa':123,'bbb':233,'ccc':333 }">
<s:property value="key"/>____<s:property value="value"/><br>
</s:iterator>
<s:iterator value="{'aaa','bbb','ccc'}" var="i">
<s:property value="i"/><br>
</s:iterator>
3-2 %号
- 强制解析ognl表达式
<!-- 模拟用户名回显的操作 -->
<%
request.setAttribute("username", "德子向前冲");
%>
<s:textfield name="username" value="%{#request.username}" label="用户名"></s:textfield>
- 强制不解析ognl表达式
3-3 $号
- 在配置文件中使用ognl
配置文件
xml文件
${值栈中变量}
4、struts2的拦截器(重要)
4-1 什么是拦截器
Interceptor:拦截器,起到拦截Action的作用。
Filter:过滤器,过滤从客户端向服务器发送的请求。
Interceptor:拦截器,拦截是客户端对Action的访问。更细粒度化的拦截。(拦截Action中的具体的方法)。
Struts2框架核心的功能都是依赖拦截器实现。
4-2 Struts2的执行流程
客户端向服务器发送一个Action的请求,执行核心过滤器(doFilter)方法。在这个方法中,调用executeAction()方法,在这个方法内部调用dispatcher.serviceAction();在这个方法内部创建一个Action代理,最终执行的是Action代理中的execute(),在代理中执行的execute方法中调用ActionInvocation的invoke方法。在这个方法内部递归执行一组拦截器(完成部分功能),如果没有下一个拦截器,就会执行目标Action,根据Action的返回的结果进行页面跳转。
4-3 拦截器入门
- 搭建Struts2的环境
- 编写拦截器类
编写一个类实现Interceptor接口或者继承AbstractInterceptor类。
public class demo1 extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("拦截器1执行了。。。。。");
String invoke = invocation.invoke();
System.err.println("拦截器1执行结束了。。。。。");
return invoke;
}
}
- 对拦截器进行配置
- 第一种方式:定义拦截器进行配置
<package name="demo1" extends="struts-default" namespace="/">
<!-- =======配置拦截器======== -->
<interceptors>
<interceptor name="interceptor1" class="com.qgc.web.intercepter.demo1"></interceptor>
<interceptor name="interceptor2" class="com.qgc.web.intercepter.demo1"></interceptor>
</interceptors>
<action name="actionDemo1" class="com.qgc.web.action.actionDemo1">
<result name="success">/demo/demo1.jsp</result>
<!-- 引用拦截器 -->
<interceptor-ref name="defaultStack"></interceptor-ref><!-- 引用默认的拦截器 -->
<interceptor-ref name="interceptor1"></interceptor-ref>
<interceptor-ref name="interceptor2"></interceptor-ref>
</action>
</package>
执行结果:
拦截器1执行了。。。。。
拦截器2执行了。。。。。
action执行了。。。
jsp执行了。。。。
拦截器2执行结束了。。。。。
拦截器1执行结束了。。。。。。
- 第二种方式:定义一个拦截器栈的方式
<package name="demo1" extends="struts-default" namespace="/">
<!-- =======配置拦截器======== -->
<interceptors>
<interceptor name="interceptor1" class="com.qgc.web.intercepter.demo1"></interceptor>
<interceptor name="interceptor2" class="com.qgc.web.intercepter.demo2"></interceptor>
<!-- 定义一个拦截器栈 -->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="interceptor1"></interceptor-ref>
<interceptor-ref name="interceptor2"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="actionDemo1" class="com.qgc.web.action.actionDemo1">
<result name="success">/demo/demo1.jsp</result>
<!-- 引用拦截器栈 -->
<interceptor-ref name="myStack"></interceptor-ref>
</action>
</package>
5、struts2的标签库
5-1 通用标签库
- <s:if>、<s:elseif>、<s:else>
- <s:iterator>
- 其他常用的标签
<s:property/>
<s:debug/>
<s:date />----在页面上进行日期格式化。