现在的位置: 首页 > 综合 > 正文

struts2_ ONGL表达式语言

2018年05月11日 ⁄ 综合 ⁄ 共 8279字 ⁄ 字号 评论关闭

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,OGNL是一个开源项目,读者可以访问其官方站点www.ognl.org以获得源代码和相关资料。OGNL是一种功能强大的EL(Expression Language,表达式语言),可以通过简单的表达式来访问Java对象中的属性,而不是直接调用对象的获取和设置方法可以提供许多应用。比如在XML文件或者脚本文件中嵌入OGNL表达式语法,在JSP页面展现层使用OGNL表达式语法。类似的应用有Velocity,Freemark,Webwork。OGNL先在WebWork项目中得到应用,也是Struts
2框架视图默认的表达式语言,可以说,OGNL表达式是Struts 2框架的特点之一。
  一、OGNL基础知识
  OGNL是将视图元素(例如textfield、combobox等)同模型对象绑定在一起的一种语言。使用OGNL的类型转换功能,会使类型转换变得更加简单(例如将一个字符串类型转换为一个整数类型)。

  表格元素同Swing TableModel对应的一种数据源语言。
  可以将Web页面元素同后台服务器业务对象对应起来。
  比JSTL(JSP标准标签库)表达更加丰富。
  OGNL 语法
  OGNL支持丰富的表达式,单语法很简单。例如有一个man对象,该对象有一个name属性,那么使用OGNL来获得该name属性可以使用如下表达式:
  man.name
  OGNL表达式的基础单元称为导航链,简称为链。一个最简单的链由如下部分组成。
   △说明
  OGNL表达式基于OGNL上下文中的当前对象,一个“链”将使用上一个“链”的处理结果,开发者可以任意扩展该链的长度,OGNL没有限制。
  例如,一个OGNL表达式如下:
  name.toCharArray()[0].numericValue.toString()
  
  该表达式将按照如下步骤求值。
  (1)获得OGNL Context中初始对象或者是根对象(root对象)的name对象。
  (2)调用toCharArray()方法,返回一个String类型对象。
  (3)获得该String对象的第一个字符。
  (4)获得该字符的numericValue属性(该字符为一个Character对象,该对象有一个getNumericValue()方法,该方法返回一个Integer类型值)。

  (5)将获得的Integer对象转换为一个String类型值(使用toString()方法)。
  
  再例:
  注:使用OGNL表达式,需要在www.ognl.org网站下载一个ognl.jar插件包,将该文件复制到classpath路径下即可。建立一个复合类型,如代码8.1所示。

  Struts2 已包含此包:ognl-2.6.11.jar
  (一)定义类:Team,Person
  
  import java.util.Date;
  //团队类
  public class Team {
  // 团队名称
  private String teamname;
  // 定义团队人员属性
  private Person person;
  // 团队人数
  private int personnum;
  //属性的getter和setter方法
  public String getTeamname() {
  return teamname;
  }
  public void setTeamname(String teamname) {
  this.teamname = teamname;
  }
  public Person getPerson() {
  return person;
  }
  public void setPerson(Person person) {
  this.person = person;
  }
  public int getPersonnum() {
  return personnum;
  }
  public void setPersonnum(int personnum) {
  this.personnum = personnum;
  }
  }
  // 定义人员类
  class Person {
  // 姓名
  private String name;
  // 年龄
  private int age;
  // 人员出生日期
  private Date birthday;
  //属性的getter和setter方法
  public String getName() {
  return name;
  }
  public void setName(String name) {
  this.name = name;
  }
  public int getAge() {
  return age;
  }
  public void setAge(int age) {
  this.age = age;
  }
  public Date getBirthday() {
  return birthday;
  }
  public void setBirthday(Date birthday) {
  this.birthday = birthday;
  }
  }
  (二)使用OGNL表达式
  import java.util.HashMap;
  import java.util.Map;
  import ognl.Ognl;
  import ognl.OgnlException;
  public class TestOGNL {
  public static void main(String[] args) {
  //定义一个Map对象
  Map m = new HashMap();
  //定义一个Team对象
  Team team1 = new Team();
  team1.setTeamname("团队1");
  //定义一个Person对象
  Person person1 = new Person();
  person1.setName("pla1");
  //添加team元素
  team1.setPerson(person1);
  //定义一个Team对象
  Team team2 = new Team();
  team2.setTeamname("团队2");
  //定义一个Person对象
  Person person2 = new Person();
  person2.setName("pla2");
  //添加team元素
  team2.setPerson(person2);
  //添加Map元素
  m.put("team1", team1);
  m.put("team2", team2);
  try {
  System.out.println(Ognl.getValue("team1.teamname", m));
  System.out.println(Ognl.getValue("team2.person.name", m));
  System.out.println(Ognl.getValue("teamname", team2));
  System.out.println(Ognl.getValue("person.name", team2));
  } catch (OgnlException e) {
  }
  }
  }
  以上代码定义了一个Map类型的嵌套属性,如图:
  图8.1 嵌套属性示意图
  运行该示例,控制器显示如下信息:
  团队1
  pla2
  团队2
  pla2
  △说明
  OGNL可以使用非常简单的表达式来访问多层嵌套属性,为开发者提供了一个有力的工具。
  二、 Struts 2的OGNL
  OGNL是Struts 2框架的默认表达式语言,增强了Struts 2的数据访问能力,同时简化了代码。
  (一)Struts 2的OGNL表达式
  标准的OGNL会设定一个根对象(root对象)。假设使用标准OGNL表达式来求值(不使用Struts 2的OGNL表达式),如果OGNL上下文(OgnlContext Map类型)有两个对象:foo对象,在OgnlContext中名称为foo;bar对象,在OgnlContext中名称为bar。同时foo对象被设置为根对象(root)。则利用下面的OGNL表达式求值:

  #foo.blah // 调用foo.getBlah()
  #bar.blah //调用bar.getBlah()
  blah //调用foo.getBlah() ,因为foo为根对象
  △说明
  如果要访问的对象不是根对象,如示例中的bar对象,则需要使用命名空间,用“#”来标识,如“#bar”;如果访问一个根对象,则不用指定命名空间,可以直接访问根对象的属性。

  在Struts 2框架中,值栈(Value Stack)就是OGNL的根对象,假设值栈中存在两个对对象实例:Man和Animal,这两个对象实例都有一个name属性,Animal有一个species属性,Man有一个salary属性,假设Animal在值栈的顶部,Man在Animal后面,下面的代码片断会帮助读者更好地理解OGNL表达式:

  Man
  属性:name
  属性:salary
   Animal 类
  属性:name
  属性:species
  species // 调用animal.getSpecies()
  salary // 调用man.getSalary()
  name // 调用animal.getName(),因为Animal位于
  值栈的顶部
  最后一行示例代码,返回的是animal.getName()返回值,即返回了Animal的name属性,因为Animal是值栈的顶部元素,OGNL将从顶部元素搜索,所以会返回Animal的name属性值。如果要获得Man的name值,则需要如下代码:

  man.name
  Struts 2允许在值栈中使用索引,示例代码如下所示:
  [0].name // 调用animal.getName()
  [1].name // 调用man.getName()
  △注意
  使用索引,并不是直接获得指定的元素,而是从指定的索引位置取属性值。
  (二)Struts 2中用OGNL表达式访问内置对象
  Struts 2中的OGNL Context是ActionContext,如图8.2所示。
  图8.2 Struts 2的OGNL Context结构示意图
  △ 说明
  图8.2只是说明Struts 2的OGNL Context结构,实际上Context还包含其他对象。
  由于值栈是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,则可以直接通过下面的代码访问值栈中的属性:
  //获得值栈中的foo属性
  ${foo}
  如果访问其他Context中的对象,由于不是根对象,在访问时,需要加#前缀。
  application对象: 用于访问ServletContext,例如#application.userName或者#application['userName'],相当于调用Servlet的getAttribute("username")。

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

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

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

  attr对象: 用于按page-request-session-application顺序访问其属性。
  (三)Struts 2中用OGNL表达式操作集合对象
  ONGL表达生可以直接生成List对象或者Map对象。
  1、使用代码直接生成一个List对象:
  {e1,e2,e3…}
  该OGNL表达式中,直接生成了一个List对象,该List对象中包含3个元素:e1、e2和e3。如果需要更多的元素,可以按照这样的格式定义多个元素,多个元素之间使用逗号隔开。

  2、如下代码可以直接生成一个Map对象:
  #{key1:value1,key2:value2,…}
  
  Map类型的集合对象,使用key-value格式定义,每个key-value元素使用冒号标识,多个元素之间使用逗号隔开。
  对于集合类型,OGNL表达式可以使用in和not in两个元素符号。其中,in表达式用来判断某个元素是否在指定的集合对象中;not in判断某个元素是否不在指定的集合对象中,如代码8.3所示。

  代码8.3 使用OGNL集合操作符
  
  
  
  
  除了in和not in之外,OGNL还允许使用某个规则获得集合对象的子集,常用的有以下3个相关操作符。
  ?:获得所有满足条件的元素。
  ^:获得满足条件的第一个元素。
  $:获得满足条件的最后一个元素。
  例如代码:
  person.relatives.{? #this.gender == 'male'}
  该代码可以获得person的所有性别为male的relatievs集合。
  (一)在控制器中使用OGNL
  仍使用前例的Person人员信息类。
  控制器类:
  import java.util.Date;
  import java.util.LinkedList;
  import java.util.List;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import javax.servlet.http.HttpSession;
  import org.apache.struts2.ServletActionContext;
  import com.opensymphony.xwork2.ActionContext;
  import com.opensymphony.xwork2.ActionSupport;
  public class OgnlAction extends ActionSupport {
  //List类型属性
  private List persons;
  //execute方法
  public String execute() throws Exception {
  // 获得ActionContext实例,以便访问Servlet API
  ActionContext ctx = ActionContext.getContext();
  // 存入application
  ctx.getApplication().put("msg", "application信息");
  // 保存session
  ctx.getSession().put("msg", "seesion信息");
  // 保存request信息
  HttpServletRequest request = ServletActionContext.getRequest();
  request.setAttribute("msg", "request信息");
  //为persons赋值
  persons = new LinkedList();
  Person person1=new Person();
  person1.setName("pla1");
  person1.setAge(26);
  person1.setBirthday(new Date());
  persons.add(person1);
  
  Person person2=new Person();
  person2.setName("pla2");
  person2.setAge(36);
  person2.setBirthday(new Date());
  persons.add(person2);
  Person person3=new Person();
  person3.setName("pla3");
  person3.setAge(16);
  person3.setBirthday(new Date());
  persons.add(person3);
  return SUCCESS;
  }
  public List getPersons() {
  return persons;
  }
  public void setPersons(List persons) {
  this.persons = persons;
  }
  }
  该控制器分别在application、session和request中存入名为“msg”的字符串信息,另外定义了一个List类型属性,同时添加了两个Person类型元素。

  (二)JSP视图中使用ONGL
  showognl.jsp是使用了OGNL表达式的JSP视图,视图用来显示Action中处理的各种信息,读者可以看到,使用OGNL表达式,代码更加简洁和直观,如代码8.5所示。

  代码8.5 使用OGNL表达式的JSP视图
  http://www.w3.org/TR/ xhtml1/DTD/xhtml1-transitional.dtd">
  http://www.w3.org/1999/xhtml">
  访问OGNL上下文和Action上下文
  parameters:
  request.msg:
  session.msg:
  application.msg:
  attr.msg:
  ________________________________________
  用于过滤和投影(projecting)集合
  年龄大于20
  • - 年龄:
  姓名为pla1的年龄:
  ________________________________________
  构造Map
  The value of key "foo1" is
   运行示例
  在浏览器中输入http://localhost:8080/bookcode/ch8/OgnlAction.action?msg=hello,运行结果如图8.3所示。

  图8.3 Struts 2中使用OGNL表达式
  △说明
  本示例演示了如何使用OGNL表达式来访问OGNL上下文和值栈,同时演示了如何使用OGNL表达式进行集合操作。对读者深入理解Struts 2中OGNL表达式的使用有所帮助。

  (三)使用ONGL中的#、$符号
  1.#符号
  #符号的用途一般有三种:
  (1)访问非根对象属性,例如示例中的#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀。实际上,#相当于ActionContext. getContext();#session.msg表达式相当于ActionContext.getContext().getSession(). getAttribute("msg") 。

  (2)用于过滤集合,如示例中的persons.{?#this.age>20}。
  (3)用来构造Map,例如示例中的#{'foo1':'bar1', 'foo2':'bar2'}。
  图8.4 “%”的OGNL表达式用法
  2.$符号
  $符号主要有两个方面的用途。
  (1)在国际化资源文件中,引用OGNL表达式,例如国际化资源文件中的代码:reg.agerange=国际化资源信息:年龄必须在${min}同${max}之间。

  在Struts 2框架的配置文件中引用OGNL表达式,例如下面的代码片断所示:
  10
  100
  BAction-test校验:数字必须为${min}为${max}之间。

抱歉!评论已关闭.