Struts2学习笔记三(OGNL表达式与值栈)

    xiaoxiao2025-06-05  16

    这是学习过程中的一些记录,可能有出错的地方,仅供参考

    值栈的简介

    在Servlet中,servlet在与前端页面之间的数据传输是通过域对象来做中转的,那么在Struts2中也有他自己做定义的一个数据中转站,这个中转站就是值栈ValueStack。

    值栈的生命周期

    值栈是Struts2的一个接口,当有页面请求时Struts2就会为我们创建好一个值栈的实现类OgnlValueStack对象,同时Struts2也会创建一个ActionContext对象和Action对象,然后将值栈封装在ActionCOntext对象中,值栈的生命周期是与Action息息相关的,Action存在则值栈存在,Action消亡则值栈也消亡。

    值栈的内部结构

    总体来看,值栈的数据结构就是一个栈,底层实现是list,在值栈中主要看两个存贮数据的区域,一个是root区,一个是context区。 root区底层又是用ArrayList实现的,而context区是用Map实现的。

    root区

    当有请求访问时,Struts2会创建一个Action实例,还会把action对象放到值栈的root区,注意所有放入值栈的都是放入对象的地址引用。在root区中,当放入的是一个对象,也会把对象内的成员属性也一并放入root区,因此Action对象中定义的成员属性也会被放入root区。

    context区

    在context区中存放着request、session、application等对象,注意这个的request、session等都只是map集合的key,而value这是request等key所对应的request对象中的数据。

    值栈的查看

    在Struts2中,我们可以通过使用Struts2的标签库来查看值栈的root区和context区。 注意要导入struts2的标签库。<%@taglib prefix=“s” uri="/struts-tags" %> 在jsp页面写入标签<s:debug></s:debug>,这样我们就可以在浏览器查看到值栈的内部结构。

    root区: context区: 往值栈的root区存值 package com.wzm.action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.CompoundRoot; import com.opensymphony.xwork2.util.ValueStack; import com.wzm.entity.User; public class ActionDemo6 extends ActionSupport{ /* * 向值栈的root区存储数据有两种方式, * 一种是属性存值,因为struts2会吧action对象存在值栈的root区, * 因此action对象里边的成员属性也会一并存在root区, * 注意是存在值栈root区的Property Name+Property Value * 另一种方式则是通过ActionContext获取值栈对象ValueStack,然后通过值栈获取root区CompoundRoot对象 * 调用push(user),底层是调用add(0, user)方法就可以往root区存值, * 注意这里是存在list下标为0的区域,相当存在root区的栈顶,同时如果是对象,会把对象内的属性存在Property Name+Property Value */ //在action中直接定义一个成员属性,struts2会把这个属性存在root区 //注意有个条件就是要有这个属性的getter方法 private User user; public User getUser() { return user; } private String jsp; public String getJsp() { return jsp; } @Override public String execute() throws Exception { /* * 通过获取root区的对象来往栈顶存值,其实不用获取root区对象也能实现功能 * valueStack.push(user);同样是往root区存值,底层调用的还是add(0, user) */ //获取actioncontext对象 ActionContext context = ActionContext.getContext(); //获取值栈对象 ValueStack valueStack = context.getValueStack(); //获取root区对象 CompoundRoot root = valueStack.getRoot(); user = new User(); user.setAge(18); jsp = "/ognl.jsp"; //往root区存值 root.push(user); return "success"; } } 往值栈的context区存值 package com.wzm.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.util.CompoundRoot; import com.opensymphony.xwork2.util.ValueStack; import com.wzm.entity.User; public class ActionDemo7 extends ActionSupport{ @Override public String execute() throws Exception { ActionContext context = ActionContext.getContext(); /* * 这里是向值栈中的context区存值 * 能够通过el表达式获取到${context区中的key} * 之前说这个有点类似往request域对象中存值,但是实际上不是, * 这是在context区中单独再创一个键值对出来,而不是在request中创建键值对 */ context.put("msg", "context"); //这里获取session,往session存值,也是通过值栈存值 //session的引用存在值栈的context区中 Map<String, Object> session = context.getSession(); session.put("a", "a"); return "success"; } }

    OGNL表达式

    OGNL的全称是对象图导航语言(Object-Graph Navigation Language),它是一种功能强大的开源表达式语言,使用这种表达式语言,可以通过某种表达式语法,存取Java对象的任意属性,调用Java对象的方法,同时能够自动实现必要的类型转换。OGNL表达式不是Struts2专属的,Struts2只是对其进行了封装。

    OGNL表达式的基本使用 注:需要导入struts2的标签库 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- 要使用OGNL表达式,需要导入struts2的标签库 --> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <!-- 这是debug标签,通过这个可以看到值栈的内部结构 --> <s:debug></s:debug> <!-- property是struts2的标签,用来使用ognl表达式获取值 --> <!-- ognl表达式可以用来直接调用对象方法 --> <s:property value="'struts2'.length()"/><br> <!-- ognl表达式可以用来直接调用静态属性,注意格式@全限定名@静态属性 --> <s:property value="@java.lang.Math@PI"/><br> <!-- ognl表达式可以用来直接调用静态方法,注意格式@全限定名@静态方法 同时注意struts2默认不让调用静态方法,需要覆盖配置 在struts.xml或者web.xml加都可以 <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> --> <s:property value="@java.lang.Math@random()"/> <!-- ognl表达式可以用来获取值栈中的值 ,value中使用的值是值栈中root区的Property Name 如果存储的是一个对象,还可以通过对象.属性名来获取对象内的属性值 --> <s:property value="user.username"/> </body> </html> Struts2中el表达式

    EL表达式原来的搜素顺序: page Scope——>request Scope——>sessionScope——>application Scope 在struts2中,struts2框架通过使用装饰者模式对request对象进行了包装,并且对getAttribute方法进行了增强,使得el表达式的搜索顺序变为了: page Scope—>request Scope—>root区—>context区- >sessionScope—>application Scope 因此当我们往context区中存数据时,我们可以使用el表达式得到存储的数据。

    el表达式的三种特殊符号 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- 要使用OGNL表达式,需要导入struts2的标签库 --> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <!-- 这是debug标签,通过这个可以看到值栈的内部结构 --> <s:debug></s:debug> <!-- ognl表达式的几个特殊符号# % $ --> <!-- 当在ognl表达式中使用到#,代表是从值栈的context区中获取值 value中使用的值的context区的key --> <s:property value="#request"/> <!-- #还可以用在遍历值栈中得到的集合 --> <!-- 直接在value中创建一个list集合 遍历出来的每一个值都存在var中,var是存在值栈的context区,因此取值需要加# 每一次都会被覆盖 --> <s:iterator value="{'aaa','bbb','ccc'}" var="l"> <s:property value="#l"/> </s:iterator> <!-- 直接在value中创建一个map集合,注意这里需要使用 # 来表明这是一个map集合 遍历出来的每一个值都存在var中,map遍历出来的是键值对 取值用#var.key或者key,#var.value获取值 --> <s:iterator value="#{'1':'a','2':'b' }" var="m"> <s:property value='#m.key'/>---》<s:property value='#m.value'/> </s:iterator> <!-- %在ognl表达式的使用 在struts2中不是所有的struts2标签都认识ognl表达式, 因此当我们需要在其他struts2标签中使用ognl表达式就需要用到% --> <s:textfield name="username" value="%{user.username}"></s:textfield> <!-- $在ognl表达式中是使用在struts.xml配置文件中的,注意与el表达式区分 通过使用 $ 符号我们可以直接在struts.xml中使用ognl表达式获取值栈的值 往值栈存储key为jsp的值,获取jsp的值“/ognl.jsp”直接跳转页面 <package name="test6" extends="struts-default"> <action name="demo6" class="com.wzm.action.ActionDemo6"> <result>${jsp}</result> </action> </package> --> </body> </html>
    最新回复(0)