OGNL表达式语言介绍

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,
它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
OGNL相对其它表达式语言具有下面几大优势:

  1. 支持对象方法调用,如xxx.doSomeSpecial();
  2. 支持类静态的方法调用和值访问,表达式的格式:
    @[类全名(包括包路径)]@[方法名 | 值名],例如:
    @java.lang.String@format(‘foo %s’, ‘bar’)
    或@tutorial.MyConstant@APP_NAME;

  3. 支持赋值操作和表达式串联,如price=100, discount=0.8,
    calculatePrice(),这个表达式会返回80;

  4. 访问OGNL上下文(OGNL context)和ActionContext;

  5. 操作集合对象。

    Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map的接口.


理解Struts2中的 ValueStack

ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础

  • ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
  • Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中

  • 在 ValueStack 对象的内部有两个逻辑部分:

    • ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中–List
    • ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
      Struts 会把下面这些映射压入 ContextMap 中
    • parameters: 该 Map 中包含当前请求的请求参数
    • request: 该 Map 中包含当前 request 对象中的所有属性
    • session: 该 Map 中包含当前 session 对象中的所有属性
    • application:该 Map 中包含当前 application 对象中的所有属性
    • attr: 该 Map 按如下顺序来检索某个属性: request, session,
      application

断点执行如下代码:

Object ctx = ServletActionContext.getRequest().getAttribute("struts.valueStack");

这里写图片描述

这里写图片描述

理解OGNL Context

  • OgnlValueStack 类包含两个重要的属性 一个root和一个context。

    • 其中root本质上是一个ArrayList.
    • 而context 是一个Map(更确切的说是一个OgnlContext对象)
  • 在这个OgnlContext对象(context)中,有一个默认的顶层对象
    _root,OGNL访问context中这个默认顶层对象中的元素时,是不需要#号的,直接通过元素的名称来进行访问,

  • 而访问其他对象时,如 request、session、attr等,则需要#号引用。
    注:Struts2将OgnlValueStack的root对象赋值给了OgnlContext 中的_root对象,在OgnlValueStack的root对象中,保存着调用Action的实例,因此,在页面上通过Struts2标签访问Action
    的属性时,就不需要通过#号来引用

    总结:ognl Context包含 ObjectStack属性和ContextMap属性

这里写图片描述


OGNL Context是struts2的数据中心 结构示意图如下:
这里写图片描述

当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。
注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:

理解ActionContext

这里写图片描述


通过代码获取ValueStack对象

1. 编写jsp测试页面和跳转页面

<%@ page language="java" pageEncoding="utf-8" contentType="text/html; charset=utf-8"%>
<%@ taglib uri="/struts-tags"   prefix="s"%>
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
    </head>
  <body>
      测试值栈:<br>
        <a href="${pageContext.request.contextPath}/ognl/ValueStackAction_test.action">test</a><br>
        <br>
        <br>
        <br>

</html>

这里写图片描述

<%@ page language="java" pageEncoding="utf-8"%>
<%@ taglib uri="/struts-tags"   prefix="s"%>
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="description" content="This is my page">
  </head>
  <body>
     valueStack.jsp页面<br>
  </body>
</html>

这里写图片描述

2.配置struts_ognl.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="ognl" namespace="/ognl" extends="struts-default">
        <action name="*_test" class="cn.itcast.ognl.{1}" method="test">
            <result name="ValueStack">/ognl/ValueStackAction.jsp</result>
        </action>
    </package>
</struts>

3.在struts.xml文件中引入自定义配置文件

<include file="cn/itcast/ognl/struts_ognl.xml"></include>

4.编写Action文件

在文件中编写代码获取ValueStack对象

package cn.itcast.ognl;

import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
import com.sun.org.apache.bcel.internal.generic.NEW;

@SuppressWarnings("serial")
public class ValueStackAction extends ActionSupport {

    public String test(){
        System.out.println("ValueStackAction ************ test()");

        HttpServletRequest request = ServletActionContext.getRequest();
        request.setAttribute("username", "username_request");
        request.setAttribute("password", "password_request");

        Map sessionMap = ServletActionContext.getContext().getSession();
        sessionMap.put("username", "username_session");
        sessionMap.put("password", "password_session");

        ServletContext sc = ServletActionContext.getServletContext();
        sc.setAttribute("username", "username_application");
        sc.setAttribute("password", "password_application");

        //方法一:获取ValueStack对象
        ValueStack valueStack1 = (ValueStack)request.getAttribute("struts.valueStack");
        System.out.println("valueStack = "+valueStack1);

        /*
         * 插入的内容,实际上是先放置在一个map集合中,又把这个map集合放置在对象栈里
         */
        valueStack1.set("error", "error_valueStack");
        valueStack1.set("msg", "msg_valueStack");

//      valueStack1.getRoot().add(0, new Person());

        //方法二:获取ValueStack对象
        /*ValueStack valueStack2 = ServletActionContext.getContext().getValueStack();
        System.out.println("valueStack = "+valueStack2);*/


        return "ValueStack";
    }

}

5.测试结果

这里写图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐