关于struts2的值栈以及OGNL

 面向对象面向君,不负代码不负卿。 *^o^*
  1. 关于值栈:
    ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
    Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中

为了便于说明:
首先有这么一个Action类。名字叫做ValueStack,位置:com.struts.valuestack.ValueStack包下。

public class ValueStack implements SessionAware,RequestAware {
    private  String name ;
    private  String price ;
    private Map<String,Object> sessionMap ;
    private Map<String,Object> requestMap ;
    public String getName() {
        return name;
    }

    public String getPrice() {
        return price;
    }

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

    public void setPrice(String price) {
        this.price = price;
    }
    public ValueStack(){

    }
    public String execute(){
        requestMap.put("test",new Test()) ;
        sessionMap.put("file",this)  ;
        return  "OK" ;
    }

    @Override
    public void setRequest(Map<String, Object> map) {

        requestMap =  map;
    }

    @Override
    public void setSession(Map<String, Object> map) {
        sessionMap  =  map;
    }
}

然后一个index.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
<s:debug></s:debug>
<br><br>
<form action="valuestack.action" method="post">
    <input type="text" name="name"><br>
    <input type="text" name="price"><br>
    <input type="submit" value="submit">
</form>
</body>
</html>

struts.xml配置

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

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

<struts>
    <%--开启允许访问静态的方法--%>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
    <package name="valuestack_1" extends="struts-default">
        <action name="valuestack" class="com.struts.valuestack.ValueStack" method="execute">
            <result name="OK" >/success.jsp</result>
        </action>
    </package>
</struts>

success.jsp页面

<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <s:debug></s:debug>
    name:${name}
    <br>
     <%--读取对象栈中的属性值--%>
    name:^$<s:property value="name"></s:property>
    <br>
    price:${price}
    <br>
    <%--读取Map栈中的属性值--%>
    map+name:<s:property value="#session.file.name"></s:property>
    map+test:<s:property value="#request.test.test_K"></s:property>
    <br>
    <%--这个request并不是原生的了 是被struts包装过的了--%>
    request:<%=request%>
    <br>
    <%--OGNL 访问静态字段和静态方法 struts.xml 需要开启--%>
    <%--访问Java的Math下的PI 页面显示3.142--%>
    <s:property value="@java.lang.Math@PI"></s:property>
    <br>
    <%--访问Java的Math下的cos() 传入0 cos1 页面显示1--%>
    <s:property value="@java.lang.Math@cos(0)"></s:property>
    <br>
    <%--调用对象栈中的方法,为属性赋值--%>
    <s:property value="setName('wewie')" ></s:property>
    <s:property value="name"></s:property>
    <br>
     <%--访问数组--%>
    <%
      String names[] = {"aa","bb","cc"} ;
      request.setAttribute("names",names);
    %>
     <%--数组长度 页面显示 3--%>
    <s:property value="#attr.names.length"></s:property>
    <br>
     <%--数组的第一个值 页面显示 aa--%>
    <s:property value="#attr.names[0]"></s:property>
      <%--数组的第3个值 页面显示 cc--%>
     <br>
    ^^^:${requestScope.names[2]}
    <br>
    <%--使用OGNL 访问Map--%>
    <%
        Map<String,String> letters = new HashMap<>() ;
        letters.put("AA","a") ;
        letters.put("BB","b") ;
        letters.put("CC","c") ;
        request.setAttribute("letters",letters);

    %>
     <%--map长度 页面显示3--%>
     <br>
    <s:property value="#attr.letters.size"></s:property>
    <%--map第一个 页面显示a--%>
    <br>
    <s:property value="#attr.letters['AA']"></s:property>
</body>
</html>

在index输出参数2321和2131
success.jsp界面显示


[Debug] name:2321 
name:^$2321 
price:2131 
map+name:2321 map+test:test 
request:org.apache.struts2.dispatcher.StrutsRequestWrapper@566133d8 
3.142 
1.0 

name:wewie 
3 
aa 
^^^:cc 

3 
a

1). 在success.jsp页面, ${name},${price} 读取 name和price 值, 实际上该属性并不在 request 等域对象中, 而是从值栈中获取的.

2). ValueStack:

I. 可以从 ActionContext 中获取值栈对象
II. 值栈分为两个逻辑部分
在 ValueStack 对象的内部有两个逻辑部分:
ObjectStack: Struts 把 Action 和相关对象压入 ObjectStack 中
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中. 实际上就是 对 ActionContext 的一个引用
Struts 会把下面这些映射压入 ContextMap 中

        parameters: 该 Map 中包含当前请求的请求参数
        request: 该 Map 中包含当前 request 对象中的所有属性
        session: 该 Map 中包含当前 session 对象中的所有属性
        application:该 Map 中包含当前 application  对象中的所有属性
        attr: 该 Map 按如下顺序来检索某个属性: request, session, application
Map 栈: 实际上是 OgnlContext 类型, 是个 Map, 也是对 ActionContext 的一个引用. 里边保存着各种 Map: requestMap, sessionMap, applicationMap, parametersMap, attr

对象栈: 实际上是 CompoundRoot 类型, 是一个使用 ArrayList 定义的栈. 里边保存各种和当前 Action 实例相关的对象.是一个数据结构意义的栈.
  1. Struts2 利用 s:property 标签和 OGNL 表达式来读取值栈中的属性值
    关于OGNL概念:参考百度百科的OGNL。OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
    支持对象方法调用,如xxx.doSomeSpecial();
    支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format(‘foo %s’, ‘bar’)或@tutorial.MyConstant@APP_NAME;
    支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(price*discount),这个表达式会返回80;
    访问OGNL上下文(OGNL context)和ActionContext;
    操作集合对象。
    可以直接new一个对象。

    1). 值栈中的属性值:

    对于对象栈: 对象栈中某一个对象的属性值

    Map 栈: request, session, application 的一个属性值 或 一个请求参数的值.

    2). 读取对象栈中对象的属性:

    若想访问 Object Stack 里的某个对象的属性. 可以使用以下几种形式之一:

    object.propertyName ; object[‘propertyName’] ; object[“propertyName”]

    ObjectStack 里的对象可以通过一个从零开始的下标来引用. ObjectStack 里的栈顶对象可以用 [0] 来引用,
    它下面的那个对象可以用 [1] 引用.

    [0].message

    [n] 的含义是从第 n 个开始搜索, 而不是只搜索第 n 个对象

    若从栈顶对象开始搜索, 则可以省略下标部分: message

    结合 s:property 标签:

    3). 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶.
    4).若希望访问值栈中 ContextMap 中的数据, 需要给 OGNL 表达式加上一个前缀字符 #. 如果没有前缀字符 #, 搜索将在 ObjectStack 里进行

    读取 Context Map 里的对象的属性:

若想访问 ContextMap 里的某个对象的属性, 可以使用以下几种形式之一:
#object.propertyName ; #object['propertyName'] ;#object["propertyName"] 
示例:
返回 session 中的 code 属性: #session.code
返回 request 中的 customer 属性的 name 属性值: #request.customer.name
返回域对象(按 request, session, application 的顺序)的 lastAccessDate 属性: #attr.lastAccessDate

调用字段和方法

可以利用 OGNL 调用
任何一个 Java 类里的静态字段或方法.
被压入到 ValueStack 栈的对象上的公共字段和方法. 
默认情况下, Struts2 不允许调用任意 Java 类静态方法,  需要重新设置 struts.ognl.allowStaticMethodAccess 标记变量的值为 true. 
调用静态字段或方法需要使用如下所示的语法:
@fullyQualifiedClassName@fieldName: @java.util.Calendar@DECEMBER
@fullyQualifiedClassName@methodName(argumentList): @app4.Util@now()
调用一个实例字段或方法的语法, 其中 object 是 Object Stack 栈里的某个对象的引用:
.object.fieldName: [0].datePattern
.object.methodName(argumentList): [0].repeat(3, “Hello”);

访问数组类型的属性

有些属性将返回一个对象数组而不是单个对象, 可以像读取任何其他对象属性那样读取它们. 这种数组型属性的各个元素以逗号分隔, 并且不带方括号
可以使用下标访问数组中指定的元素: colors[0]
可以通过调用其 length 字段查出给定数组中有多少个元素: colors.length

访问 List 类型的属性

有些属性将返回的类型是 java.util.List, 可以像读取任何其他属性那样读取它们. 这种 List 的各个元素是字符串, 以逗号分隔, 并且带方括号
可以使用下标访问 List 中指定的元素: colors[0]
可以通过调用其 size 方法或专用关键字 size 的方法查出给定List 的长度: colors.size 或 colors.size()
可以通过使用 isEmpty() 方法或专用关键字 isEmpty 来得知给定的 List 是不是空. colors.isEmpty 或 colors.isEmpty()
还可以使用 OGNL 表达式来创建 List, 创建一个 List 与声明一个 Java 数组是相同的: {“Red”, “Black”, “Green”}

访问 Map 类型的属性

读取一个 Map 类型的属性将以如下所示的格式返回它所有的键值对: 
{key_1=value_1,......}
若希望检索出某个 Map 的值, 需要使用如下格式: map[key] 
可以使用 size 或 size() 得出某个给定的 Map 的键值对的个数
可以使用 isEmpty 或 isEmpty() 检查某给定 Map 是不是空. 
可以使用如下语法来创建一个 Map: 
#{key_1=value_1,........}

使用 EL 访问值栈中对象的属性

<s:property value=“fieldName”> 也可以通过 JSP EL 来达到目的: ${fieldName}
原理: Struts2 将包装 HttpServletRequest 对象后的 org.apache.struts2.dispatcher.StrutsRequestWrapper 对象传到页面上, 而这个类重写了 getAttribute() 方法.   
   大牛,别默默看了。快登陆帮我评论吧! *^o^*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值