Struts2——OGNL和ValueStack

本文详细介绍了Struts2框架中的核心组件ValueStack的作用、获取方式及其内部结构。包括ValueStack如何作为Action和视图间数据交互的桥梁,以及其内部的root和context区域的数据存取方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、概念

(1)OGNL是Object Graphic Navigation Language(对象图导航语言)。Struts2框架使用OGNL作为默认的表达式语言。OGNL就是EL的升级版。
作用:Action和视图(JSP)之间数据交互的桥梁.

(2)值栈是对应每一个请求对象的轻量级的内存数据中心。每一次请求的时候,都会创建一个新的ValueStack对象,该ValueStack对象封装了这一次请求相关的数据信息.

①ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。
②ValueStack贯穿整个Action的生命周期(一次请求):每个Action类的实例都拥有一个ValueStack对象。 ValueStack相当于数据的中转站,在其中保存该次请求和当前Action对象和其他相关对象信息。
③Struts2框架把ValueStack对象保存在名为“struts.valueStack”的request属性中。
新的请求:
ValueStack vs = ....;
request.setAttribute("struts.valueStack",vs);

2、获取ValueStack对象

(1)方式一: 在ValueStack在请求中,ValueStack对象属性名为:struts.valueStack
        ValueStack stack1 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");
        ValueStack stack2 = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

(2)方式二:通过ActionContext对象获取:推荐
        ValueStack stack3 = ActionContext.getContext().getValueStack();

3、ValueStack内部结构

从OgnlValueStack源码可以看到以下两个属性:


①root——类型:CompoundRoot extends CopyOnWriteArrayList。

主要存储Action对象相关的数据信息。一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以action对象是CompoundRoot中的一个元素。有push()、pop()方法,是个栈结构。

从root中获取数据: 直接使用属性名获取. ---><s:property value="属性名"/>

②context(上下文)——类型: Map。主要存储映射关系数据.(key-value).

从context中获取数据: #key ---><s:property value="#key"/>

ActionContext为Action的上下文,其中有重要的6大对象valueStack,parameters,request,session,application,attr               

ognl表达式必须选择AcitonContext中的一个对象作为根对象(root),默认为valueStack,因此访问valueStack中的数据不加#

4、值栈root区域值的存取

(1)存入数据


(2)取出数据

必须使用Struts的标签.--->先引入Struts2标签<%@ taglib uri="/struts-tags" prefix="s"%>
访问方式:<s:property value="OGNL表达式"/>

放入root中的数据,没有属性名。

取出栈顶数据:<s:property value="[0].top"/>

放入root中的数据,有属性名

取出栈顶数据:<s:property value="属性名"/>



5、值栈context区域值的存取

(1)存入数据


(2)取出数据


6、Struts2标签

可查看:OGNL表达式struts2标签“%,#,$”的区别

(1)Control Tag

eg:if、elseif、else


测试:


eg:iterator



(2)Form Tag

eg:theme默认为xhtml


测试:


7、输入校验

Action中
* 要继承ActionSupport
* 重写Validateable接口中的validate()方法 ,在该方法中完成验证
步骤如下:
* validate()方法在其他的业务方法之前执行
* 验证出错转向的页面
struts.xml配置<result name="input">页面地址</result>
* 什么时候表示验证出错(转向input所指向的页面)
* super.addFieldError("字段名称", "错误信息");
* 当集合不为空时,转向错误页面.
* 若校验失败,不会再执行Action中的业务方法.

以下示例校验用户名是否为空

eg:

①log.jsp

<%@ taglib uri="/struts-tags" prefix="s"%>
<h3>登录页面</h3>
<s:form action="/validate"  namespace="/" method="post" theme="simple">
	用户:<s:textfield name="username"/><br>

    <!-- 显示错误信息 -->

  <s:fielderror value="username"/>密码:<input type="text" name="password"><br><input type="submit" value="提交"></s:form>

②ValidationAction.java

public class ValidationAction extends ActionSupport{

	private static final long serialVersionUID = 1L;
	private String username;
	private String password;
	public String login(){	
		System.out.println(username+","+password);
		return "none";
	}
	@Override
	public void validate(){
		if(username == null || "".equals(username)){
			//super.addFieldError("字段名称", "错误信息")
			super.addFieldError("username", "用户名不能为空");
			//return INPUT视图
		}
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
}

③struts.xml

<struts>
	<package name="valiPkg" namespace="/" extends="struts-default">
		<action name="validate" class="action.validation.ValidationAction" method="login">
			<result name="input">/views/validate/log.jsp</result>
		</action>
	</package>
</struts>

注意:一定要配置INPUT类型的结果视图

④测试:若不填用户名则返回登录页面,否则在控制台打印用户名和密码。


⑤此时在Action类增加两个方法

public void save(){
		System.out.println("保存");
		<action name="validate_*" class="action.validation.ValidationAction" method="{1}">
			<result name="input">/views/validate/log.jsp</result>
                        <allowed-methods>save,delete</allowed-methods>
              </action>

}public void delete(){System.out.println("删除");}

⑥在struts.xml修改配置

		<action name="validate_*" class="action.validation.ValidationAction" method="{1}">
			<result name="input">/views/validate/log.jsp</result>
                        <allowed-methods>save,delete</allowed-methods>
              </action>

⑦测试:

可以看到连save、delete方法都进行了验证


为了避免对不需要的方法进行验证,有如下两种方法:

i.在不需要进行校验的方法上添加@SkipValidation注解

ii. 想要验证那个方法,按照规则和一个新的方法:方法名规则 validate + 需要验证的方法名,方法名首字母大写



测试:

可继续参考:

Struts2数据传输的背后机制:ValueStack(值栈)

struts ValueStack 详解


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值