JavaWeb开发知识总结(六)-(struts2_ognl_valuestack_interceptor)

JavaWeb开发知识总结(struts2-ognl_valueStack_interceptor)

1. ognl表达式

​ OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。 类似EL表达式,但功能更强大。Ognl导航类似于Java中的链式编程,ognl表达式的导航本质是使用get和set方法进行获取/设置数据

ognl表达式的作用:

  1. 支持对象的操作,调用对象的方法;
  2. 支持静态成员访问;
  3. 支持赋值操作与表达串联;
  4. 访问OGNL上下文,访问OgnlContext对象;
  5. 操作集合对象。

ognl在struts2中的作用:

# ognl是表达式,和el表达式类似,el表达式用在jsp中获取域对象里面的值
1. ognl也是一种表达式,比el表达式功能更加强大;
2. 使用ognl主要作用:在struts2里面获取值栈中存储的数据。
# ognl本身不是struts2一部分,而是单独项目,经常和struts2一起使用
* 要使用ognl首先导入jar包,在struts2里面支持ognl,默认提供ognl的jar包。
# 在struts2里面获取值栈数据
* ognl在struts2里面和struts2标签一起使用,来获取值栈中的数据。

ognl作用案例:项目中需要导入ognl的jar包ognl-3.0.6.jar

// ognl表达式的作用:
public class StrutsOgnlDemo1 {
   
    @Test
    /**
     * 功能1: ognl操纵对象
     * ognl表达式的三要素:表达式,ognlContext对象,root对象
     */
    public void demo1() throws OgnlException {
        // 1.创建ognlContext上下文对象
        OgnlContext context = new OgnlContext();
        // 2.操作对象
        // Object value = Ognl.getValue("'somnus'", context, new Object());
        // 从root中获取的值是somnus字符串
        // Object value = Ognl.getValue("'somnus'.length()", context, new
        // Object()); // root中获取的值是somnus字符串的长度
        // Object value = Ognl.getValue("#somnus", context, new Object()); 
        // 从Context中获取的值是somnus属性,不存在返回null
        // Object value = Ognl.getValue("somnus", context, new Object()); 
        // 从root中获取的值是somnus属性,不存在时报错
        // 在Context中有对root的引用
        Object root = context.getRoot();
        Object value = Ognl.getValue("somnus", context, root);
        // 报错
        System.out.println(value);
    }
    /**
     * 功能2: ognl访问静态常量和静态方法
     */
    @Test
    public void demo2() throws OgnlException {
        // 1.获取Context对象
        OgnlContext context = new OgnlContext();
        // 2.获取root对象
        Object root = context.getRoot();
        // 3.执行表达式,访问静态常量
        Object value = Ognl.getValue("@java.lang.Math@PI", context, root);
        System.out.println(value);
        // 访问静态方法
        Object value2 = Ognl.getValue("@java.lang.Math@random()", context, root);
        System.out.println(value2);
    }
    /**
     * 功能3:ognl的Context对象
     * Context对象本质是Map集合
     * 访问Context中的数据需要加#
     */
    @Test
    public void demo3() throws OgnlException{
        // 1.获取Context对象
        OgnlContext context = new OgnlContext();
        // 2.获取root对象
        Object root = context.getRoot();
        // 3.向Context中存储数据
        context.put("somnus", "sunmos");
        // 4.通过表达式取出数据
        Object value = Ognl.getValue("#somnus", context, root);
        System.out.println(value);
    }
    /**
     * 功能3:ognl的root对象
     * root对象本质是list集合
     * 访问Context中的数据不需要加#
     */
    @Test
    public void demo4() throws OgnlException{
        // 1.获取Context对象
        OgnlContext context = new OgnlContext();
        // 2.获取root对象,获取root对象,需要在context设置root后才能获取
        // Object root = context.getRoot();
        // 3.向Context中存储Map集合数据
        Map<String, String> map = new HashMap<String, String>();
        map.put("username", "somnus");
        context.put("username", "sunmos");
        // 将map设为root
        context.setRoot(map);
        Object root = context.getRoot();
        // 4.通过表达式取出数据,取出root中的数据,不能加#
        Object value = Ognl.getValue("username", context, root); // 值是somnus
        // 4.通过表达式取出数据,取出context中的数据,不能加#
        // Object value = Ognl.getValue("#username", context, root); // 值是sunmos
        System.out.println(value); // 输出时somnus
    }
    /**
     * 功能4:操作集合
     */
    @Test
    public void demo5() throws OgnlException {
        // 1.获取Context对象
        OgnlContext context = new OgnlContext();
        // 2.获取root
        Object root = context.getRoot();
        // 3.操作集合
        Object value = Ognl.getValue("{'hello','good','well'}", context,root);
        System.out.println(value.getClass()); // class java.util.ArrayList
        // list集合的数据可以存储在root中
        context.setRoot(value);
        // 取出root中的数据
        Object value2 = Ognl.getValue("[0]", context, root);// 取出List集合中索引为0的值
        //相当于创建了一个Map集合,和上述创建List集合不能同时存在
        // Object value3 = Ognl.getValue("#{'username':'tom','age':20}", context,context.getRoot()); 
        // System.out.println(value3.getClass()); // class java.util.LinkedHashMap
        // System.out.println(value3); // {username=tom, age=20}
    }

    /**
     * 功能5:赋值及表达式串联
     */
    @Test
    public void demo6() throws OgnlException {
        // 1.获取上下文对象OgnlContext
        OgnlContext context = new OgnlContext(); // 它就是一个java.util.Map

        //2.操作ognl表达式
        //相当于创建了一个Map集合
        Object value = Ognl.getValue("#{'username':'tom','age':20}", context,context.getRoot()); 
        // 将值设为root
        context.setRoot(value);
        // 取出root中的值及为root中值赋值
        // Object value2 = Ognl.getValue("username,age=45", context,context.getRoot()); // 值为45
        // Object value3 = Ognl.getValue("username", context,context.getRoot()); // 值为tom
        Object value3 = Ognl.getValue("username='somnus'", context,context.getRoot()); //值为somnus
        System.out.println(value3);
    }
}

struts2中使用ognl表达式:

​ 在struts2框架中我们使用ognl表达式的作用是从valueStack中获取数据。我们在struts2框架中可以使用ognl+valueStack达到在页面(jsp)上来获取相关的数据。在jsp页面上使用ognl表达式,就需要结合struts2框架的标签需要导入strutss2的标签库,struts2-tags,简写是s,在jsp页面使用< s:property value=”表达式”>来使用。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<html><head>
<title>ognl在struts2中的使用</title>
</head><body>
<!-- 获取somnus字符串的长度 -->
<s:property value="'somnus'.length()"/>
<!-- 获取Math类的常量值PI -->
<s:property value="@java.lang.Math@PI"/>
<!-- 获取Math类的随机数 -->
<s:property value="@java.lang.Math@random()"/>
</body></html>

2. valueStack值栈

​ 在Servlet中是通过域对象(3个域对象)向前端页面传递数据,将数据存储到域中,在前端页面jsp中通过EL表达式获取域对象中的数据。

​ 在struts2中action处理完数据后需要携带数据到前端页面上,struts2中使用valueStack值栈方式存储数据。valueStack本质是一个数据容器。valueStack类似Servlet的域对象,valueStack是存储在每一个action中,在前端页面jsp中可以通过ognl表达式(也可以是EL表达式)获取值栈中存储的数据。

2.1 Servlet与action的区别:(重点)

​ Servlet默认是在第一次被请求访问时创建对象,只创建一次,单实例对象,每次请求访问Servlet都会重新开启一个线程去执行service方法进行处理请求。

​ Action会在每次请求访问时都会重新创建一个对象,多实例对象

2.2 action的生命周期:(个人理解)

​ valueStack被设计成是一个接口com.opensymphony.xwork2.util.ValueStack,struts2基于ognl表达式提供了实现类com.opensymphony.xwork2.ognl.OgnlValueStack,根据查看action执行过程可知:action的生命周期

当客户端向发送一个请求,服务器就会创建一个Action来处理请求,每一次请求都会有一个新的action对应(多实例,不存在线程安全问题);Struts2会根据每一次的http请求来创建对应的ActionContext(与当前线程绑定),每一次请求对应一个线程来处理request请求,同时为action实例创建一个单独的valueStack对象并将其存储到request域中;valueStack值栈和ActionContext对象都是随着Action实例的创建而存在,随着Action的销毁而消失,valueStack是存储在request域中,则valueStack的生命周期和request的生命周期相同,则Action生命周期和request生命周期相同,request的生命周期是一次请求一次响应范围。
rquest---->ActionContext---->Action---->ValueStack是一一对应的关系,其生命周期都和request相同,是一次请求一次响应范围。

2.3 valueStack值栈内部结构

​ 通过查看值栈的源码可知,值栈由两部分组成root和Context。并且root本质是ArrayList集合,Context本质是linkedHashMap集合。一般存储的数据都是存储在root中,Context中存储的是对象的引用。与action相关的数据存储到root中,与Servlet的API相关的数据存储到Context中。root模拟的是栈结构形式的存取数据。在jsp页面使用struts的<s:dubeg> 标签可以查看值栈的结构。同时Context中存储了root的引用。

root中存储数据类型:

​ root中存储的是action相关的数据,action每次被访问时创建实例对象,struts2会将当前action的实例存储到root的栈底,当action中有模型对象时会将模型对象也存储到root栈中,同时在action中声明的属性都会存储到root中栈中。如果action声明任何属性或模型时,action实例对象是位于root中的栈顶。

Context中存储的数据类型:本质是Map集合,存储的是对象引用,key值是固定的

Map集合的key Map集合的value
request 本次请求HttpServletRequest对象的引用
session 本次会话HttpSession对象引用
application web应用的ServletContext对象引用
parameters 本次请求的所有参数的封装引用
attr 获取Servlet三个域中存储的值,当存储的名称相同时,获取是域范围最小的中存储的值
对象(会变) 当jsp页面使用< s:iterator value=”集合” var=”p”> 声明var变量时,会将p对象引用存储在Context中

2.4 valueStack值栈对象的获取

​ 值栈是存储在每次请求的request域中,则可以先获取request对象,再从request中获取valueStack对象;每次action被访问时创建ActionContext对象,并向其中存储valueStack对象,则可以通过ActionContext对象获取valueStack对象。值栈对象针对每一个action实例只有一个实例对象。

// 在action中任意一个方法中均可以获取:
// 第一种方式:通过ServletActionContext获取request对象,再获取request域中存储的valueStack对象
ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
// 第二种方式:通过actionContext对象获取valueStack对象
ValueStack valueStack2 = ActionContext.getContext().getValueStack();

2.5 向valueStack中存储数据

​ 向值栈中存储数据,主要是都是存储在root中的;struts2框架会自动向root中存储数据(两类);在action中向valueStack中存储数据有两种方式。

struts2框架自动向root中存储数据:

​ 通过查看源码可知,struts2框架会向值栈的root中存储数据(两类):第一类是将当前的action对象存储到root的栈底;第二类是将action的模型驱动封装的模型(需要action实现ModelDriven接口)或成员属性(属性需要提供get方法)存储到root中。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值