Struts 2 值栈(Value Stack)/OGNL

值栈(ValueStack)就是 OGNL 表达式存取数据的地方。在一个值栈中,封装了一次请求所需要的所有数据。

在使用 Struts2 的项目中,Struts2 会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的关系,这种一一对应的关系使值栈能够线程安全地为每个请求提供公共的数据存取服务。

值堆栈是一组几个对象,它们按照提供的顺序保持以下对象

序号 对象 描述
1 Temporary Objects 在页面执行期间会创建各种临时对象。 例如,在 JSP 标记中循环的集合的当前迭代值。
2 The Model Object 如果在 struts 应用程序中使用模型对象,则当前模型对象将放置在值堆栈上的操作之前。
3 The Action Object 这将是正在执行的当前动作对象。
4 Named Objects 这些对象包括 #application#session#request#attr#parameters 并引用相应的servlet 范围。

可以通过为 JSPVelocityFreemarker 提供的标签访问值堆栈。 我们将在单独的章节中学习各种标签,用于获取和设置 struts 2.0 值堆栈。 我们可以在 Action 中获取 valueStack 对象,如下所示

ActionContext.getContext().getValueStack()

一旦有了 ValueStack 对象,就可以使用以下方法来操作该对象

序号 方法 描述
1 Object findValue(String expr) 通过以默认搜索顺序对堆栈评估给定表达式来查找值。
2 CompoundRoot getRoot() 获取包含推入堆栈的对象的 CompoundRoot。
3 Object peek() 在不改变堆栈的情况下获取堆栈顶部的对象。
4 Object pop() 获取堆栈顶部的对象并将其从堆栈中删除。
5 void push(Object o) 将此对象放在堆栈的顶部。
6 void set(String key, Object o) 使用给定的键在堆栈上设置一个对象,以便可以通过 findValue(key,...) 检索它
7 void setDefaultType(Class defaultType) 如果在获取值时未提供类型,则设置要转换为的默认类型。
8 void setValue(String expr, Object value) 尝试使用默认搜索顺序使用给定表达式在堆栈中的 bean 上设置属性。
9 int size() 获取堆栈中的对象数。

OGNL

Object-Graph Navigation Language (OGNL) 是一种强大的表达式语言,用于引用和操作 ValueStack 上的数据。 OGNL 还有助于数据传输和类型转换。

OGNL 与 JSP 表达式语言非常相似。 OGNL 基于在上下文中拥有根或默认对象的想法。 可以使用标记符号(即井号#符号)来引用默认对象或根对象的属性。

如前所述,OGNL 基于上下文,Struts 构建了一个 ActionContext 映射以与 OGNL 一起使用。 ActionContext 映射包括以下内容

  • Application - 应用程序范围的变量
  • Session - 会话范围的变量
  • Root / value stack - 你所有的 Action 变量都存储在这里
  • Request - 请求范围变量
  • Parameters - 请求参数
  • Atributes - 存储在页面、请求、会话和应用程序范围中的属性

重要的是要了解 Action 对象在值堆栈中始终可用。 因此,如果 Action 对象具有属性“x”和“y”,那么我们可以随时使用。

ActionContext 中的对象使用 # 符号引用,但是,可以直接引用值堆栈中的对象。

例如,如果employee是一个action类的属性,那么可以如下引用

<s:property value = "name"/>

从而代替如下的引用

<s:property value = "#name"/>

如果我们在会话中有一个名为“login”的属性,可以按如下方式检索它

<s:property value = "#session.login"/>

OGNL 还支持处理集合——即 MapListSet。 例如,要显示颜色的下拉列表,我们可以这样做

<s:select name = "color" list = "{'red','yellow','green'}" />

OGNL 表达式很聪明地将“red”、“yellow”、“green”解释为颜色并以此为基础构建列表。

当我们将研究不同的标签时,OGNL 表达式将在下一章中广泛使用。 因此,与其孤立地查看它们,不如让我们使用表单标签/控件标签/数据标签和 Ajax 标签部分中的一些示例来进一步的了解它们。

ValueStack/OGNL 示例

创建 Action

让我们考虑以下 Action 类,我们在其中访问 valueStack,然后设置一些我们将在视图中使用 OGNL 访问的键,即 JSP 页面。

package com.jiyik.struts2.action;


import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;

import java.util.HashMap;
import java.util.Map;

public class HelloWorldAction extends ActionSupport {

    private String name;

    @Override
    public String execute() throws Exception {
        ValueStack stack = ActionContext.getContext().getValueStack();
        Map<String, Object> context = new HashMap<String, Object>();

        context.put("key1", new String("This is key1"));
        context.put("key2", new String("This is key2"));

        stack.push(context);
        System.out.println("值堆栈的大小为:"+ stack.size());
        return SUCCESS;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

实际上,Struts 2 在执行时会将我们的 Action 添加到 valueStack 的顶部。 因此,将东西放在值堆栈上的常用方法是将值的 getter/setter 添加到 Action 类,然后使用 <s:property> 标记来访问这些值。 但正在向大家展示 ActionContext 和 ValueStack 在 struts 中的工作原理。

创建视图

让我们在项目的 Web 文件夹中创建 jsp 文件 HelloWorld.jsp。 如果 Action 返回 SUCCESS,将显示此视图

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello World</title>
</head>
<body>
Entered value : <s:property value = "name"/><br/>
Value of key 1 : <s:property value = "key1" /><br/>
Value of key 2 : <s:property value = "key2" /> <br/>
</body>
</html>

我们还需要在Web文件夹中创建 index.jsp,其内容如下

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
  <h1>Hello World From Struts2</h1>
  <form action = "hello">
    <label for = "name">请输入您的姓名</label><br/>
    <input type = "text" name = "name"/>
    <input type = "submit" value = "Say Hello"/>
  </form>
  </body>
</html>

配置文件

以下是 struts.xml 文件的内容

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name = "struts.devMode" value = "true" />

    <package name = "helloworld" extends = "struts-default">
        <action name = "hello"
                class = "com.jiyik.struts2.action.HelloWorldAction"
                method = "execute">
            <result name = "success">/HelloWorld.jsp</result>
        </action>
    </package>
</struts>

以下是 web.xml 文件的内容

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

代码和配置文件都完成之后,接下来让我们在 IDEA 中启动项目。项目启动之后,在浏览器中访问 http://localhost:8080/index.jsp。 页面如下所示

Struts 运行示例

现在在给定的文本框中输入任何单词,然后单击“Say Hello”按钮来执行定义的操作。 显示的页面内容如下所示

Struts 显示值堆栈的页面

现在,如果检查生成的日志,我们会在底部找到以下文本

Struts 打印值堆栈的大小

查看笔记

扫码一下
查看教程更方便