Struts2之OGNL

1.什么是OGNL?

       OGNL 是 Object-Graph Navigation Language 的缩写,从语言角度来说:它是一个功能强大的表达式语言,用来获取和设置 java 对象的属性 , 它旨在提供一个更高抽象度语法来对 java 对象图进行导航,OGNL 在许多的地方都有应用,例如:

     1)作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言。

     2)数据库表到 Swing 的 TableModel 的数据源语言。

     3)web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) 。

     4)作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言。

另外,java 中很多可以做的事情,也可以使用 OGNL 来完成,例如:列表映射和选择。对于开发者来说,使用 OGNL,可以用简洁的语法来完成对 java 对象的导航。通常来说:通过一个“路径”来完成对象信息的导航,这个“路径”可以是到 java bean 的某个属性,或者集合中的某个索引的对象,等等,而不是直接使用 get 或者 set 方法来完成。

2.OGNL的基本语法

       OGNL 表达式一般都很简单。虽然 OGNL 语言本身已经变得更加丰富了也更强大了,但是一般来说那些比较复杂的语言特性并未影响到 OGNL 的简洁:简单的部分还是依然那么简单。比如要获取一个对象的 name 属性,OGNL 表达式就是 name, 要获取一个对象的 headline 属性的 text 属性,OGNL 表达式就是 headline.text 。 OGNL 表达式的基本单位是“导航链”,往往简称为“链”。最简单的链包含如下部分:

表达式组成部分      示例

属性名称           如上述示例中的 name 和 headline.text

方法调用           hashCode() 返回当前对象的哈希码。

数组元素           listeners[0] 返回当前对象的监听器列表中的第一个元素。

       所有的 OGNL 表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将作为后面求值的上下文。你的链可以写得很长,例如:

name.toCharArray()[0].numericValue.toString()

上面的表达式的求值步骤:

提取根 (root) 对象的 name 属性。

调用上一步返回的结果字符串的 toCharArray() 方法。

提取返回的结果数组的第一个字符。

获取字符的 numericValue 属性,该字符是一个 Character 对象,Character 类有一个 getNumericValue() 方法。

调用结果 Integer 对象的 toString() 方法。

3.OGNL表达式

    OGNL 表达式

   1)常量:字符串:“ hello ” 字符:‘ h ’ 数字:除了像 java 的内置类型 int,long,float 和 double,Ognl 还有如例:

0.01B,相当于 java.math.BigDecimal,使用’ b ’或者’ B ’后缀。 100000H,相当于 java.math.BigInteger,使用’ h ’ 或 ’ H ’ 后缀。

   2)属性的引用例如:user.name

  3)变量的引用例如:#name

  4)静态变量的访问使用 @class@field

  5)静态方法的调用使用 @class@method(args), 如果没有指定 class 那么默认就使用 java.lang.Math.

  6)构造函数的调用例如:new java.util.ArrayList();

4.表达式语言的好处

   表达式语言主要有以下几大好处:

   1)避免(MyType) request.getAttribute()和myBean.getMyProperty()之类的语句,使页面更简洁;

   2)支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能;

   3)简单明了地表达代码逻辑,使用代码更可读与便于维护。

5.Stuts2支持的表达式语言

     Struts 2支持以下几种表达式语言:

1)OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言;

2)JSTL(JSP Standard Tag Library),JSP 2.0集成的标准的表达式语言;

3)Groovy,基于Java平台的动态语言,它具有时下比较流行的动态语言(如Python、Ruby和Smarttalk等)的一些起特性;

4)Velocity,严格来说不是表达式语言,它是一种基于Java的模板匹配引擎,具说其性能要比JSP好。

     Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:

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

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

       支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(),这个表达式会返回80;

       访问OGNL上下文(OGNL context)和ActionContext;

       操作集合对象。

6.OGNL的相关知识

   1.OGNL表达式的计算是围绕OGNL上下文进行的。
       OGNL上下文实际上就是一个Map对象,由ognl.OgnlContext类表示。它里面可以存放很多个JavaBean对象。它有一个上下文根对象。
上下文中的根对象可以直接使用名来访问或直接使用它的属性名访问它的属性值。否则要加前缀“#key”。

   2.Struts2的标签库都是使用OGNL表达式来访问ActionContext中的对象数据的。如:<s:property  value="xxx"/>。

   3.Struts2将ActionContext设置为OGNL上下文,并将值栈作为OGNL的根对象放置到ActionContext中。
   4.值栈(ValueStack) :
    可以在值栈中放入、删除、查询对象。访问值栈中的对象不用“#”。
    Struts2总是把当前Action实例放置在栈顶。所以在OGNL中引用Action中的属性也可以省略“#”。
    5.调用ActionContext的put(key,value)放入的数据,需要使用#访问。

7.OGNL三个符号 % $ #的使用

   OGNL中重要的3个符号:#、%、$:

#、%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分,需要时间的积累才渐渐弄清楚……
1.#符号

#符号的用途一般有三种。

—    访问非根对象属性,例如#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute("msg") 。

—    用于过滤和投影(projecting)集合,如persons.{?#this.age>25},persons.{?#this.name=='pla1'}.{age}[0]。

—    用来构造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。

2.%符号

%符号的用途是在标志的属性为字符串类型时,计算OGNL表达式的值,这个类似js中的eval,很暴力。

3.$符号

$符号主要有两个方面的用途。

—    在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。

—    在Struts 2框架的配置文件中引用OGNL表达式

举例说明:

package com.demo.action;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class TestAction extends ActionSupport {

	private List<User> users;
	private HttpServletRequest request;
	private Map session;
	private Map application;

	public void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	public void setSession(Map<String, String> session) {
		this.session = session;
	}

	public void setApplication(Map<String, String> application) {
		this.application = application;
	}

	public void setList(List<User> users) {
		this.users = users;
	}

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	public String execute() {
		ActionContext act = ActionContext.getContext();
		request = ServletActionContext.getRequest(); // 获得request对象
		session = act.getSession(); // 获得session对象
		application = act.getApplication(); // 获得application对象

		request.setAttribute("userName", "from Request");
		session.put("userName", "from session");
		application.put("userName", "form application");
		users = new ArrayList<User>();
		users.add(new User("zhangsan", "beijing", 18));
		users.add(new User("lisi", "chaoyang", 25));
		users.add(new User("wangwu", "beijing", 20));

		return SUCCESS;

	}

}


User。java

package com.demo.action;

public class User {
	
	private String username;
	private String address;
	private int age;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public User(String username, String address, int age) {
		super();
		this.username = username;
		this.address = address;
		this.age = age;
	}
	

}

ognl。jsp


<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Struts OGNL Demo</title>
</head>
<body>    
    <h3>访问OGNL上下文和Action上下文</h3>
    <p>parameters: <s:property value="#parameters.userName" /></p>
    <p>request.userName: <s:property value="#request.userName" /></p>
    <p>session.userName: <s:property value="#session.userName" /></p>
    <p>application.userName: <s:property value="#application.userName" /></p>
    <p>attr.userName: <s:property value="#attr.userName" /></p>
    <hr />
    <h3>用于过滤和投影(projecting)集合</h3>
    <p>age more than 18</p>
    <ul>
        <s:iterator value="users.{?#this.age > 18}">
            <li> username:<s:property value="username" />---<s:property value="address" /></li>
        </s:iterator>
    </ul>
    <p>The address of "beijing" is: <s:property value="users.{?#this.address=='beijing'}.{username}[0]"/></p>
    <hr />
    <h3>构造Map</h3>
    <s:set name="foobar" value="#{'foo1':'bar1', 'foo2':'bar2'}" />
    <p>The value of key "foo1" is <s:property value="#foobar['foo1']" /></p>
    
    <hr />
    <h3>%的用途</h3>
    <p><s:url value="#foobar['foo1']" /></p>
    <p><s:url value="%{#foobar['foo1']}" /></p>
</body>
</html>


 struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />
    <package name="default" namespace="" extends="struts-default">
        <action name="test" class="com.demo.action.TestAction">
            <result type="dispatcher">/ognl.jsp</result>
            <result name="input">/index.jsp</result>
        </action>
        <action name="user_*" class="com.demo.action.UserAction" method="{1}">
             <result name="login">/login.jsp</result>
             <result name="register">/success.jsp</result>      
        </action>
        
    </package>
</struts>


Struts2之OGNL_第1张图片

 

 

 

 

 

 

 

你可能感兴趣的:(Struts2之OGNL)