Struts2 OGNL

 Struts2中的OGNL表达式语言

OGNLObject Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts 2框架使用OGNL作为默认的表达式语言。

相对EL表达式,它提供了平时我们需要的一些功能,如:

支持对象方法调用,如xxx.sayHello()

支持类静态方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format('foo %s', 'bar')@cn.csdn.Constant@APP_NAME

操作集合对象。

Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了java.utils.Map接口,在Struts2中上下文(Context)的实现为ActionContext,下面是上下文(Context)的结构示意图

 

Struts 2中的OGNL Context实现者为ActionContext,它结构示意图如下:

 
Struts2 OGNL
 

Struts2接受一个请求时,会迅速创建ActionContextValueStackaction 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。

访问上下文(Context)中的对象需要使用#符号标注命名空间,如#application#session

另外OGNL会设定一个根对象(root对象),在Struts2中根对象就是ValueStack(值栈) 。如果要访问根对象(即ValueStack)中对象的属性,则可以省略#命名空间,直接访问该对象的属性即可。

 

struts2中,根对象ValueStack的实现类为OgnlValueStack,该对象不是我们想像的只存放单个值,而是存放一组对象。在OgnlValueStack类里有一个List类型的root变量,就是使用他存放一组对象

|--request

|--application

context ------|--OgnlValueStack root变量[action, OgnlUtil, ... ]

|--session

|--attr

|--parameters

 

root变量中处于第一位的对象叫栈顶对象。通常我们在OGNL表达式里直接写上属性的名称即可访问root变量里对象的属性,搜索顺序是从栈顶对象开始寻找,如果栈顶对象不存在该属性,就会从第二个对象寻找,如果没有找到就从第三个对象寻找,依次往下访问,直到找到为止。

大家注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:<s:property value="name"/>

 

由于ValueStack(值栈)Struts 2OGNL的根对象,如果用户需要访问值栈中的对象,在JSP页面可以直接通过下面的EL表达式访问ValueStack(值栈)中对象的属性。

 

如果访问其他Context中的对象,由于他们不是根对象,所以在访问时,需要添加#前缀。

 

application对象:用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用ServletContextgetAttribute("username")

 

session对象:用来访问HttpSession,例如#session.userName或者#session['userName'],相当于调用session.getAttribute("userName")

 

request对象:用来访问HttpServletRequest属性(attribute)的Map,例如#request.userName或者#request['userName'],相当于调用request.getAttribute("userName")

 

parameters对象:用于访问HTTP的请求参数,例如#parameters.userName或者#parameters['userName'],相当于调用request.getParameter("username")

 

attr对象:用于按page->request->session->application顺序访问其属性。

 

 1:OGNL是对象图导航语言(Object-Graph Navigation Language)的缩写, 它是一种功能强大的表达式语言(EL),通过它简单一致的表达式语法,可以存取对象的属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化功能,它用相同的表达式语法去存取对象的属性

 

2:常量与操作符

<s:property value="'account''">,这里面的account是个字符串,因为是用单引号括起来的,或者<s:property value="7+8">这句话,结果就是15,也就是数学运算之后的值


3:方法调用

访问静态方法,访问集合对象的方法

 

4:设置数值和表达式列表

 

5:使用OGNL访问ValueStack

在OGNL中,没有前缀表示访问当前值栈。如<s:property valu="account">


6:使用OGNL访问ActionContext

在ognl中,使用符号"#"来访问ActionContext中除了值栈之外的各种值,如,

#parameters:当前请求中的参数,对应request.getParameter(name)

#request:请求作用域中的属性,对应request.getAttribute(name)

#session:会话作用域的属性,对应session.getAttribute(name)

#application:应用程序作用域的属性

#attr:按照页面page,请求request, 会话session和应用application的顺序,返回第一个符合条件的属性。

在引用的时候,需要加上前缀"#", 并制定范围,然后写出需要引用哪个属性,形如"#parameters.account"

 

在ognl中还有另外一种方式来访问属性,形如"#request['username']"等价于使用"#request.username",在访问更复杂对象的时候,两种方法可以混用。

一般情况下:如果访问对象的属性,建议使用"."的方式来改变,如果访问Map等复杂结构的时候,建议使用"[]"的方式来访问

 

 

action的内容为:

public String execute() {
		System.out.println("用户输入的参数为,username:" + username + ", password:" + password);
		
		ActionContext context = ActionContext.getContext();
		context.getSession().put("username", "session中的username");
		context.getApplication().put("username", "application中的account");
	
		return "success";
		
	}

 

页面jsp的内容:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
   Hello World!<br>
    username:<s:property value="username"/><br>
    password:<s:property value="password"/><br>
     <a href="hello.action?username=zhangsan" target="_self">Hello.action</a>
     <br/>
     请求参数中的用户名:<s:property value="#parameters.username"/>
     <br/>
     <%request.setAttribute("username", "request中的username"); %>
    请求属性中的用户名: <s:property value="#request.username"/>
     <br>
     会话属性中的用户名: <s:property value="#session.username"/>
     <br>
     应用属性中的用户名: <s:property value="#application.username"/>
     <br>
  attr中的用户名: <s:property value="#attr.username"/>
    <s:debug></s:debug>
</body>
</html>

 

7:访问静态方法和静态属性

在OGNL中,可以通过关键字"@"来访问任意类中的静态方法和静态属性,方式为"@类的全路径名@属性名称",或者"@类的全路径名@方法名称(方法参数)",如果在高版本的Struts2中,要访问类的静态方法,需要去开启设置,配置非常简单,在struts.xml中,添加开启访问类的静态方法的配置,如下所示:

<constant name="struts.ognl.allowStaticMethodAccess" value="true" />

 

8:使用ognl访问数组

OGNL表达式为:array.length,就表示访问array这个数组的length属性

list.size,表示访问list这个集合的size()方法

list.isEmpty,就表示访问list这个集合的isEmpty方法

OGNL表达式为{1, 2, 3},就表示构建一个包含3个值的集合,值分别为1, 2, 3

OGNL表达式为{1, 2, 3}[0],就表示构建一个包含3个值的集合,值分别是1, 2, 3, 然后获取索引为0的值,就是1.


9:访问map

在action中有属性: Map<String, UserModel> userMap = new HashMap<String, UserModel>();

 在页面中:

用户编号:<s:property value="userMap['umTest'].userId">

用户姓名: <s:property value="userMap['umTest'].name">

 OGNL表达式为:map.size, 就表示访问map这个Map的size

map.isEmpty, 就表示访问map这个Map的isEmpty方法


10:ActionContext

public class ActionContext implements Serializable {
static ThreadLocal actionContext = new ThreadLocal();

}

ThreadLocal 又称为”线程局部变量“, 它为每一个使用该变量的线程都提供了变量值的副本,使每一个线程都可以独立的改变自己的副本,而不会和其他线程的副本冲突。

存放在ActionContext里的数据都存放在这个ThreadLocal的属性中,而这个属性只会在对应的当前请求线程中可见,从而保证数据是线程安全的。


11:ServletActionContext

这个类直接继承自ActionContext, 当然也继承了它父类的很多功能,比如:对OgnlValueStack、Action名字等的访问,更重要的是,它还提供了直接访问Servlet的相关对象的功能,它可以取得的对象有:

HttpServletRequest: 请求对象

HttpServletResponse:响应对象

ServletContext: Servlet上下文信息

PageContext: Http页面上下文

你可能感兴趣的:(struts2)