文章目录


1、OGNL

1-1 什么是ognl

Struts2(三)_值栈

  • 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中的数据
    Struts2(三)_拦截器_02
  • 获取context中的数据


获取context中的数据时,表达式数据名称前面要添加#


Struts2(三)_值栈_03

1-3-2 ognl在struts2中的环境入门



  1. 首先要在jsp引入struts2的包,​​<%@ taglib uri="/struts-tags" prefix="s"%>​
  2. 在jsp中使用​​<s:property value=""/>​​标签来使用ognl表达式
  3. 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 什么是值栈

Struts2(三)_值栈_04

  • 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>​​来查看值栈中的内容

Struts2(三)_数据_05

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的返回的结果进行页面跳转。


Struts2(三)_值栈_06

Struts2(三)_值栈_07

4-3 拦截器入门


  1. 搭建Struts2的环境
  2. 编写拦截器类
    编写一个类实现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;
}

}
  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.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 通用标签库

Struts2(三)_数据_08


  • <s:if>、<s:elseif>、<s:else>
    Struts2(三)_拦截器_09
  • <s:iterator>
    Struts2(三)_拦截器_10
  • 其他常用的标签
    <s:property/>
    <s:debug/>
    <s:date />----在页面上进行日期格式化。

5-2 UI标签库(方便数据回显)

Struts2(三)_值栈_11