JAVAWEB开发之Struts2详解(四)——ognl与valueStack(重点)、Struts常用标签、防止表单重复提交、Struts2中内置json插件

本文详细介绍了Struts2中的OGNL表达式,包括其在ValueStack中的作用,以及ValueStack的结构和操作。同时,文章还讲解了Struts2中的常用逻辑标签和表单标签的使用,如property、iterator、if/else、url等,并探讨了防止表单重复提交的策略和Struts2内置JSON插件的应用。
摘要由CSDN通过智能技术生成

ognl

ognl中有一个OgnlContext,它可以设置root与非root,root中获取数据时,不需要加#,而非root数据获取时需要加#号。
简单示例如下:
OgnlDemo1
package cn.itcast.ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

public class OgnlDemo1 {

	public static void main(String[] args) throws OgnlException {
		// ognl可以通过对象调用方法

		// System.out.println("aaa".length());

		// 使用ognl来完成上面操作

		// 1.创建一个ognl上下文
		OgnlContext context = new OgnlContext();

		Object obj1 = Ognl.getValue("'aaa'.length()", context.getRoot());

		System.out.println(obj1);
	}
}


OgnlDemo2

package cn.itcast.ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

public class OgnlDemo2 {

	public static void main(String[] args) throws OgnlException {
		// ognl可以通过类调用静态方法

		System.out.println(Math.max(10, 20));
		System.out.println(Math.PI);
		// 使用ognl来完成上面操作

		// 1.创建一个ognl上下文
		OgnlContext context = new OgnlContext();

		Object obj1 = Ognl.getValue("@java.lang.Math@max(10,20)",
				context.getRoot());

		System.out.println(obj1);

		Object obj2 = Ognl.getValue("@java.lang.Math@PI", context.getRoot());

		System.out.println(obj2);
	}

}

关于存取根与非根数据如下所示:
Person
package cn.itcast.ognl;

public class Person {

	private String name;
	private Dog dog;

	public String getName() {
		return name;
	}

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

	public Dog getDog() {
		return dog;
	}

	public void setDog(Dog dog) {
		this.dog = dog;
	}

}

Dog

package cn.itcast.ognl;

public class Dog {

	private String name;

	private Person p;

	public String getName() {
		return name;
	}

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

	public Person getP() {
		return p;
	}

	public void setP(Person p) {
		this.p = p;
	}

}

OgnlDemo3
package cn.itcast.ognl;

import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;

public class OgnlDemo3 {

	public static void main(String[] args) throws OgnlException {

		// 创建一个ognl上下文
		OgnlContext context = new OgnlContext();// 本质上是一个Map集合

		Person p = new Person();
		p.setName("张三");

		Dog dog = new Dog();
		dog.setName("lucy");

		p.setDog(dog); // 张三有条狗叫lucy

		context.setRoot(p);

		Dog dog1 = new Dog();
		dog1.setName("豆豆");

		Person pp = new Person();
		pp.setName("jams");
		dog1.setP(pp);

		context.put("dog", dog1);

		context.put("name", "tom");

		// 使用ognl来获取根中数据,不需要加#
		Object name1 = Ognl.getValue("name", context, context.getRoot());

		System.out.println(name1);

		// 使用ognl来获取非根中的数据,获取非根中的数据 需要使用#
		Object name2 = Ognl.getValue("#name", context, context.getRoot());

		System.out.println(name2);

		// 获取张三的狗的名称
		Object name3 = Ognl.getValue("dog.name", context, context.getRoot());

		System.out.println(name3);

		// 获取豆豆的主人名称
		Object name4 = Ognl.getValue("#dog.p.name", context, context.getRoot());

		System.out.println(name4);

	}
}

ognl介绍

ognl是Object Graphic Navigation Language(对象导航图语言)的缩写,它是一个开源项目。Struts2框架使用ognl作为默认的表达式语言。
ognl是一种比EL强大很多倍的语言。
ognl相对其它表达式语言具有下面五大优势:
1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态方法的调用和值访问,表达式的格式:@[类全名(包括包路径)]@[方法名| 值名],例如:@java.lang.String@format("foo %s","bar");或@tutorial.MyConstant@APP_NAME;
设置:struts.ognl.allowStaticMethodAccess=true;
3、访问ognl上下文(OGNL context)和ActionContext;(重点:操作valueStack值栈)
4、支持赋值操作和表达式串联,如price=100,discount=0.8,caculatePrice(),这个表达式会返回80;
5、操作集合对象。
示例:
<h1>实例方法调用</h1>
<s:property value="'abcdef'.length()"/>
<h2>静态方法调用</h2>
<s:property value="@java.lang.String@format('你好, %s','小明')"/>
演示:在struts2中使用ognl表达式
需要结合struts2的标签使用<s:property value="ognl表达式">
<s:property value="'abc'.length()"/>  演示对象调用方法
<s:property value="@java.lang.Math@max(10,20)"/> 演示静态成员访问.
注意:在struts2中使用静态成员访问,必须设置一个常量:
struts.ognl.allowStaticMethodAccess=false
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>演示:使用ognl来通过对象调用方法</title>
</head>

<body>
	<s:property value="'abc'.length()" />
	<hr>

	<s:property value="@java.lang.Math@max(10,20)" />
</body>
</html>

Struts2中的valueStack

valueStack概述:
ValueStack实际上是一个接口com.opensymphony.xwork2.util.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
理解Struts2中的ValueStack
断点执行如下代码:
Object ctx=ServletActionContext.getRequest().getAttribute("struts.valueStack");

______________________________________________________________________________

理解OGNL Context
OGNL Context是Struts2的数据中心,结构示意图如下:

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

问题1:什么是ValueStack?

valueStack主要是将action数据携带到页面上,通过ognl获取数据
1、ValueStack有一个实现类叫OgnlValueStack。
2、每一个action都有一个ValueStack(一个请求,一个request,一个action,一个ValueStack)valueStack生命周期就是request生命周期。
3、valueStack中存储了当前action对象以及其它常用web对象(request,session,application,parameters)
4、Struts2框架将valueStack以"struts.valueStack"为名存储到request域中

ValueStack内部结构图如下:


问题2:valueStack结构?

ValueStack中存在root属性(CompoundRoot)、context属性(OgnlContext)
* CompoundRoot 就是ArrayList
* OgnlContext 就是Map
list 集合中存储的是action相关信息
map集合中存储的是相关映射信息,包含 parameters、request、session,application,attr等
想要从list中获取数据,可以不使用#号(它就是ognl的root)
如果从map中获取数据,需要使用#(其实在Struts2中的map—context其实就是OgnlContext)
结论:
ValueStack有两部分List   Map
在Struts2中List就是root,Map就是OgnlContext
默认情况下,在Struts2中从ValueStack中获取数据从root中获取

问题3:值栈对象的创建,ValueStack和ActionContext是什么关系?

ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
ValueStack是每一次请求时,都会创建
在ActionContext中持有了ValueStack的引用

ValueStack对象的创建过程
StrutsPrepareAndExecuteFilter
doFilter方法
prepare.createActionContext(request, response); 
创建ActionContext和ValueStack
ctx = new ActionContext(stack.getContext());
ActionContext引用ValueStack对象 
Dispatcher——serviceAction方法
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
将ValueStack对象 保存到request 范围


问题4:如何获得值栈对象?

对于ValueStack获取有两种方式:
1、通过request获取
ValueStack vs=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STATUS_VALUESTACK_KEY);
2、通过ActionContext获取
ValueStack vs=ActionContext.getContext().getValueStack();


问题5:向值栈中保存数据(主要针对root)

主要有两个方法
push(Object obj)----->底层就是root.add(0,obj) 将数据存储到栈顶。
set(String name,Object obj)------->底层是将数据封装到HashMap中,在将这个HashMap通过push存储。
在JSP通过<s:debug />查看值栈内容
ActionContext提供了对ognl上下文对象中数据操作的方法
ServletActionContext.getRequest().setAttribute("username", "username_request");
ServletActionContext.getServletContext().setAttribute("username", "username_application");
ServletActionContext.getContext().getSession().put("username", "username_session");
 // 获取值栈对象
ValueStack valueStack=ServletActionContext.getContext().getValueStack();
System.out.println("valueStack       "+valueStack);
 // 向值栈保存数据
valueStack.set("username", "username_valueStack");
valueStach.push("www.baidu.com");

问题6:如何在JSP中获取值栈的数据?

获取root中数据不需要#,而context中数据需要#
1、如果栈顶是一个Map集合,获取时,可以直接通过Map集合的key来获取value
<s:property value="username" />
2、如果栈顶数据不是一个Map,没有key值,可以通过序号来获取
<s:property value="[0]"> 从0的位置向下查找所有
<s:property value="[0].top"> 只查找0位置上数据(栈顶数据)
3、获取OgnlContext中的数据
request:<s:property value="#request.username"/>
session:<s:property value="#session.username"/>
application:<s:property value="#application.username"/>
attr:<s:property value="#attr.username"/>
parameters:<s:property value="#pa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值