今天分享的是Struts2框架中的一种ognl表达式语言,主要分两个目标去学习

      1.理解struts2传值的优先级

      2.ognl与el的区别

一:ognl表达式语言简介

  OGNL的全称是Object Graph Navigation Language(对象图导航语言),它是一种强大的表达式语言,让你通过简单一致的表达式语法来读取和设置Java对象的属性值,调用对象的方法,遍历整个对象的结构图,实现字段类型转换等功能。 

  1.1:简单对 对象图导航语言举例分析

     假如现在项目中有两个实体类:

   Class Book(书本类中有以下属性) :

    private String bid;
    private String bname;
    private Category c;

   Class Category(书籍分类有以下属性):   

     private String cid;
      private String name;

  假如我现在有一个需求:

    想在同一个jsp页面中展示书籍以及书籍类别的信息,

    像平时的话肯定就是写BookDao然后用list集合接收在jsp中用EL表达式输出出来

         ${book.bid}/${book.bname}

      然而${book.c.bname} 就是对象图导航语言,

二:ognl表达式语言特点 

  1.支持对象方法调用,形式如:objName.methodName();

  2.支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路)]@[方法名 |  值名],例如:

    @java.lang.String@add( '11' , 'hahhaha' )

  3.支持赋值操作和表达式串联,例如:

   number=18, price=100,Total();那么返回1800;

  4.访问OGNL上下文(OGNL context)其实就是Map (教室、老师、学生)和ActionContext,

    OgnlContext=根对象(1)+非根对象(N)
    老师:根对象 1
    学生:非根对象 n
    非根对象要通过"#key"访问,根对象可以省略"#key"

    3.4.1:根对象和非根对象的概括

      1、一个上下文中只有一个根对象
      2、取跟对象的值,只需要直接通过根对象属性即可
      3、非根对象取值必须通过指定的上下文容器中的#key.属性去取。

    图解:

    

  ognl取值赋值的方法:

  OnglExpression类

package com.ht.text;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException; /**
* 用于OGNL表达计算的一个工具类
*
*/
public class OnglExpression {
private OnglExpression() {
} /**
* 根据OGNL表达式进行取值操作
*
* @param expression
* ognl表达式
* @param ctx
* ognl上下文
* @param rootObject
* ognl根对象
* @return
*/
public static Object getValue(String expression, OgnlContext ctx, Object rootObject) {
try {
return Ognl.getValue(expression, ctx, rootObject);
} catch (OgnlException e) {
throw new RuntimeException(e);
}
}
/**
* 根据OGNL表达式进行赋值操作
*
* @param expression
* ognl表达式
* @param ctx
* ognl上下文
* @param rootObject
* ognl根对象
* @param value
* 值对象
*/
public static void setValue(String expression, OgnlContext ctx, Object rootObject, Object value) {
try {
Ognl.setValue(expression, ctx, rootObject, value);
} catch (OgnlException e) {
throw new RuntimeException(e);
}
}
}

四:值栈ValueStack 

  valueStack是struts2的值栈空间,是struts2存储数据的空间

  根据栈的制度,它是先进后出的数据结构,弹夹 push/pop

  之所以把它作为根对象主要是因为  放到值栈中的对象都可视为根对象

  4.1:ValueStack简介

  4.1.1.ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用实现了ValueStack接口的类OgnlValueStack.

  4.1.2.ValueStack贯穿整个action的生命周期,每一个action实例都拥有一个ValueStack对象,其中保存了当前action对象和其他相关对象.

  4.1.3.struts2把ValueStack对象保存在名为:struts.valueStack的request域中.即ValueStack作用域为request.当action创建的时候,ValueStack就创建了,action被销毁的时候,ValueStack就销毁了

  4.1.4.ValueStack中的数据分两部分存放:root(栈结构,CompoundRoot)和context(map形式,OgnlContext)

  (1)其中的root对象是CompoundRoot,CompoundRoot继承了ArrayList,提供了额外的方法:push(),和pop()方法,

用来对root对象中所包含的数据进行存取.正是由于这两个方法,CompoundRoot变成了一个栈结构. struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以action对象是CompoundRoot中的一个元素.

  (2)其中的context对象是OgnlContext,它实现了map接口,在valuestack的默认实现类中,即OgnlValueStack类中,

调用ongl中的方法:Ognl.createDefaultContext(..)给context赋值,此方法返回的是一个OgnlContext对象.

  ValueStack内存结构图如下:

  4.2 struts2中传递数据

  可以使用作用域,但更多的是利用ValueStackActionContext

  然而作用域取值有规律的他是从小到大的

  page -> request -> session -> application

  ActionContext就相当于一个大容器,同一请求中只创建一个上下文;

  ValueStack就是根对象容器,它的取值是从上至下的;

  parameters,request ,session ,application就是非根对象容器

  注意:

  1、ActionContext一次请求创建一次
  2、值栈取值从上往下,取到为止,如果已经拿到,不再往下找。

五:ognl与el区别

  因为OGNL表达式是struts2的默认表达式语言所以只对struts2标签管用,然而el在html中也可以用

   struts2标签用的都是ognl表达式语言,所以它多数都是去栈顶找值,找不到再去作用域

   el却相反,它都是去map集合作用域中找

  

  ognl的取值赋值案例示范

  

public class Demo1 {
2
3 /**
4 * @param args
5 * @throws OgnlException
6 */
7 public static void main(String[] args) {
8 // 叫小李的员工
9 Employee e = new Employee();
10 e.setName("小李");
11 // 张经理的管理
12 Manager m = new Manager();
13 m.setName("张经理");
14
15 // 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
16 OgnlContext ctx = new OgnlContext();
17
18 // 将员工和经理放到OGNL上下文当中去
19 ctx.put("employee", e);
20 ctx.put("manager", m);
21 // 小李是根对象 一个公司有很多老板 只有一个员工小李
22 ctx.setRoot(e);// 设置OGNL上下文的根对象
23
24 /** ********************** 取值操作 *************************** */
25 // 表达式name将执行e.getName(),因为e对象是根对象(请注意根对象和非根对象表达式的区别)
26 String employeeName = (String) OnglExpression.getValue("name", ctx, e);
27 System.out.println(employeeName); //小李
28
29 // 表达式#manager.name将执行m.getName(),注意:如果访问的不是根对象那么必须在前面加上一个名称空间,例如:#manager.name
30 String managerName = (String) OnglExpression.getValue("#manager.name",
31 ctx, e);
32 System.out.println(managerName); //张经理
33
34 // 当然根对象也可以使用#employee.name表达式进行访问
35 employeeName = (String) OnglExpression.getValue("#employee.name", ctx,
36 e);
37 System.out.println(employeeName); //小李
38
39 /** ********************** 赋值操作 *************************** */
40 OnglExpression.setValue("name", ctx, e, "小明");
41 employeeName = (String) OnglExpression.getValue("name", ctx, e);
42 System.out.println(employeeName); //小明
43
44 OnglExpression.setValue("#manager.name", ctx, e, "孙经理");
45 managerName = (String) OnglExpression.getValue("#manager.name", ctx, e);
46 System.out.println(managerName); //孙经理
47
48 OnglExpression.setValue("#employee.name", ctx, e, "小芳");
49 employeeName = (String) OnglExpression.getValue("name", ctx, e);
50 System.out.println(employeeName); //小芳
51 }
52 }

  控制台上输出结果顺序与下面一致就对了

小李
张经理
小李
小明
孙经理
小芳

  ognl在struts2中的应用

  创建一个测试类

/**
* 此例用于模拟struts2的值栈计算过程
* ValueStack是一个堆栈结构的容器 有压栈操作 先进后出
* @param args
*/
public String test1(String[] args) {
ValueStack vs =ServletActionContext.getContext().getValueStack();
vs.push(new Employee("张雇员", 2000));//
vs.push(new Student("小明同学", "s001"));//
System.out.println(vs.findValue("name"));//小明
System.out.println(vs.findValue("salary2")); //
return "rs";
}

struts-sy.xml配置文件

<action name="/stack_*"  class="com.ht.text.Demo7" method="{1}">
<result name="rs">/rs.jsp</result>
</action>

jsp中代码

<a href="${pageContext.request.contextPath }/sy/stack_test1.action?sex=nv">ognl1</a>

输出结果为

小明同学
2000

现在来用实例证明一下ValueStack有压栈,先进后出的赋值套路

  创建一个类来写action代码,记得继承ModelDriven接口

private Cal cal1=new Cal();

    private String num1;

    public String getNum1() {
return num1;
} public void setNum1(String num1) {
this.num1 = num1;
} public String accept1() {
// cal使用的是ModelDriven赋值
System.out.println("cal1:"+cal1);
// num使用的是get/set赋值
System.out.println("num1:"+num1);
return "rs";
}

jsp代码

<a href="${pageContext.request.contextPath }/sy/demo_accept1.action?num1=20&&num2=5">accept1</a>

输出结果

值栈中cal1变量比num1变量更靠近栈顶,所以她接收到了值,但是前台参数已经赋值,所以num1没有接收到值就为null了

今日分享到此结束,谢谢观看!

Struts2中OGNL表达式的用法的更多相关文章

  1. struts2中#,$,%的用法以及el,ognl表达式的用法

    OGNL, JSTL, STRUTS2标签中符号#,$,%的用法示例 取Session中的值 <c:out value="${sessionScope.user.userId}&quo ...

  2. struts2 与 OGNL 表达式,jsp中 利用ognl 在valuestack中取值

    在Struts2中,一个请求在终于到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是 ...

  3. 初窥struts2(二)OGNL表达式

    Struts2总结 Struts2完整的处理流程: 1  客户端发送请求,交给struts2控制器(StrutsPrepareAndExecuteFilter). 2  Filter控制器进行请求过滤 ...

  4. struts2(四) ognl表达式、值栈、actionContext之间的关系

    今天来说说ognl表达式在struts2中的运用. --wh 一.什么是Ognl? 通过百度百科查询到的解释,其中详细的说明了OGNL的作用. 下面我们就对OGNL这5个作用进行讲解 1.存取对象的任 ...

  5. Struts2之 OGNL表达式和值栈

    技术分析之OGNL表达式概述(了解)        1. OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写        * 所谓对象图,即以任意 ...

  6. struts2:OGNL表达式之#、%、$符号运用

    1. OGNL表达达符号"#" 1.1 #用于访问OGNL上下文和Action上下文,#相当于ActionContext.getContext() 注意:当系统创建了Action实 ...

  7. Struts2的OGNL表达式语言

    一.OGNL的概念 OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者 ...

  8. Struts2中OGNL

    什么是OGNL OGNL:Object Graph Navigation Language  对象导航图语言 开源项目,取代页面中Java脚本,简化数据访问 和EL同属于表达式语言,但功能更为强大 让 ...

  9. Struts2之OGNL表达式

    OGNL(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言,除了用来设置和获取Java对象的属性之外,另外提供诸如集合的投影和过滤以及lam ...

随机推荐

  1. bzoj2406 矩阵

    我们不妨想一想,这道题目又有\(abs\)又有\(Max\)不是很好算对吧. 所以我们二分答案,考虑怎么\(check\). 对于一个点,显然它能够取的范围是\([l,r]\),接着是对于一行一列都有 ...

  2. Cubic-bezier 曲线

    cubic-bezier又称三次贝塞尔,主要是为animation生成速度曲线函数. cubic-bezier(x1,y1,x2,y2) 此图中: P0:(0,0) P1:(x1,y1) P2:(x2 ...

  3. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  4. 雪花算法(DELPHI实现)

    雪花算法(DELPHI实现) 生成ID能够按照时间有序生成. 分布式系统内不会产生重复id(用workerId来做区分). 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景. GUID:采用无 ...

  5. yarn集群8088端口被攻击挖矿

    yarn集群8088端口被攻击挖矿 https://www.jianshu.com/p/a2d6b0d827ab https://blog.csdn.net/lm709409753/article/d ...

  6. OpenGL ES: (2) OpenGL ES 与 EGL、GLSL的关系

    OpenGL ES 是负责 GPU 工作的,目的是通过 GPU 计算,得到一张图片,这张图片在内存中其实就是一块 buffer,存储有每个点的颜色信息等.而这张图片最终是要显示到屏幕上,所以还需要具体 ...

  7. Java体系

    Java之父:詹姆斯·高斯林 java之前叫做“Oak”,后改名为Java.//Oak来源于橡树,java 来源爪哇岛的一种咖啡 Java语言平台 J2SE(Java 2 Platform Stand ...

  8. nVidia GPGPU vs AMD Radeon HD Graphics执行模式对比

    大家做高性能计算的朋友,想必对CPU的执行模式已经非常熟悉了吧.当代高级些的CPU一般采用超标量流水线,使得毗邻几条相互独立的指令能够并行执行——这称为指令集并行(ILP,Instruction-Le ...

  9. flutter 引入第三方 Icon 图标(以阿里图标库为例)

    在fluttter中引入第三方图标库的具体方法: 1.在阿里图标库选好需要用的图标,添加进购物车将选好的图标打包下载到本地(下载代码),复制iconfont.ttf文件到项目中 2.存放途径:lib/ ...

  10. 阶段5 3.微服务项目【学成在线】_day06 页面发布 课程管理_20-课程计划添加-前端页面调试

    调试课程计划的添加功能 课程添加的弹窗使用的是dialog组件 这个变量控制对话框是否显示 当点击按钮的时候就设置为true.那么弹窗就会显示出来了  测试 在测试的节点下面添加一个子节点 添加成功后 ...