sruts2中ognl表达式的原理

来源:互联网 发布:windows上tensorflow 编辑:程序博客网 时间:2024/04/29 14:23

ognl是跟struts2的标签一起使用的。Struts2结合了ognl,在ognl中有根元素的概念,在Struts2中,根对象就是ValueStack,在任何流程当中,ValueStack最顶层的对象,一定是Action对象。除了ValueStack根对象外,Struts2还提供了几个常用的非根对象,叫做命名对象:parameters, request, session, application, attr。

若访问根对象,那么在表达式中直接访问即可,若访问的不是根对象,那么就要在要访问的对象的前面加上“#”,表示访问的不是根对象。

如何访问值栈中的对象的属性?若访问的是值栈中的对象的属性,那么struts2会从栈的顶部往下寻找和表达式中指定的属性匹配的属性,若找到,就不再继续往下找。也可以不从顶部开始找起,这时就要用到方括号去指定从哪里开始找起。

下面结合例子,看一下在Struts2中,ognl是怎么使用的:

package com.suo.action;import java.util.Map;public class Person{private String name;private int age;private String address;private String[] friends;private Cat cat;private Map<String,String> map;public Person(String name, int age, String address, String[] friends,Cat cat, Map<String, String> map) {this.name = name;this.age = age;this.address = address;this.friends = friends;this.cat = cat;this.map = map;}public Person() {}public Cat getCat() {return cat;}public void setCat(Cat cat) {this.cat = cat;}public Map<String, String> getMap() {return map;}public void setMap(Map<String, String> map) {this.map = map;}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 String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String[] getFriends() {return friends;}public void setFriends(String[] friends) {this.friends = friends;}}
package com.suo.action;public class Cat {private String name;private int age;private String color;public Cat(String name, int age, String color){this.name=name;this.age=age;this.color=color;}public Cat(){}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 String getColor() {return color;}public void setColor(String color) {this.color = color;}}
package com.suo.action;import java.util.ArrayList;/** * 实现了RequestAware,SessionAware,ApplicationAware接口,是为了取得Servlet API中的request等对象, * 这也是取得这些对象的一种方法。 * 注意,这些属性一定要有对应的set方法。 * @author hackerain */public class OgnlAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{private Map<String,Object> request;private Map<String, Object> application;private Map<String, Object> session;private String username;private String password;private List<Person> list;public List<Person> getList() {return list;}public void setList(List<Person> list) {this.list = list;}@Overridepublic void setRequest(Map<String, Object> request) {this.request=request;}@Overridepublic void setApplication(Map<String, Object> application) {this.application=application;}@Overridepublic void setSession(Map<String, Object> session) {this.session=session;}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;}@Overridepublic String execute() throws Exception {request.put("hello", "suo");session.put("hello", "piao");application.put("hello", "rachel");Cat cat1=new Cat("cat1", 12, "red");Cat cat2=new Cat("cat2", 11, "blue");String[] friends1=new String[]{"gg1","gg2","gg3"};String[] friends2=new String[]{"mm1","mm2","mm3"};Map<String,String> map1=new HashMap<String,String>();Map<String,String> map2=new HashMap<String,String>();map1.put("key11", "value11");map1.put("key12", "value12");map2.put("key21", "value21");map2.put("key22", "value22");Person person1=new Person("suo",23,"changsha",friends1,cat1,map1);Person person2=new Person("piao",21,"changchun",friends2,cat2,map2);list=new ArrayList<Person>();list.add(person1);list.add(person2);return SUCCESS;}}
login.jsp:  <body>    <form action="OgnlAction">    username: <input type="text" name="username" width="20"><br>    password: <input type="password" name="password" width="20"><br>    <input type="submit" value="submit">    </form></body>
ognl.jsp:<%@ page language="java" import="java.util.*, com.opensymphony.xwork2.*, com.suo.action.OgnlAction" pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <title>My JSP 'ognl.jsp' starting page</title>  </head>    <body>  --------------------------------------------<br>    标签库实现:<br>   username: <s:property value="username"/><br>   password: <s:property value="password"/><br>      <!-- 因为此处ValueStack为根对象,而Action对象又保存到ValueStack的最顶层,所以此处不用#号指定属性的对象 -->   --------------------------------------------<br>       用parameters命名对象实现:<br>   username: <s:property value="#parameters.username"/><br>   password: <s:property value="#parameters.password"/><br>      <!--    此处用的是parameters命名对象,它和ValueStack根对象是处在同一个地位的,只是它不是根对象而已,所以   要访问命名对象中的属性,则要用#号指定对象名。request,session,application同理。    -->   --------------------------------------------<br>      底层实现:<br>   username: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getUsername() %><br>   password: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getPassword() %><br>      <!-- peek()函数是返回栈的最顶部的对象,但是并不从栈中删除这个对象,最顶部的对象为Action对象 -->      --------------------------------------------<br>      用命名对象实现:<br>   request: <s:property value="#request.hello"/><br>   session: <s:property value="#session.hello"/><br>   application: <s:property value="#application.hello"/><br>   attr: <s:property value="#attr.hello"/><br>      --------------------------------------------<br>      底层实现:<br>   request: <%=((Map)ActionContext.getContext().get("request")).get("hello") %><br>   session: <%=ActionContext.getContext().getSession().get("hello") %><br>   application: <%=ActionContext.getContext().getApplication().get("hello") %><br>   attr: <%=((Map)ActionContext.getContext().get("attr")).get("hello") %><br>      <!-- ActionContext是一个提供Action上下文环境的类,提供了getSession(),getApplication,get()等方法 -->      --------------------------------------------<br>      用标签库实现:<br>   person1.name:<s:property value="list[0].name"/><br>   person2.address:<s:property value="list[1].address"/><br>      list.size: <s:property value="list.size"/><br>   list.isEmpty: <s:property value="list.isEmpty()"/><br>      person1.cat: <s:property value="list[0].cat.name"/><br>      person2.friend1: <s:property value="list[1].friends[0]"/><br>      person1.map1: <s:property value="list[0].map"/><br>   person2.map2.key21: <s:property value="list[1].map['key21']"/><br>      <!-- 值栈是根对象,且在值栈的最顶层的对象为Action对象,所以这里可以直接指定Action中的属性来访问 -->      --------------------------------------------<br>      底层实现:<br>   person1.name: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(0).getName() %><br>   person2.address: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(1).getAddress() %><br>      list.size: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().size() %><br>   list.isEmpty: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().isEmpty() %><br>      person1.cat: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(0).getCat().getName()%><br>      person2.friend1: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(1).getFriends()[0] %><br>      person1.map1: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(0).getMap() %><br>   person2.map2.key21: <%=((OgnlAction)ActionContext.getContext().getValueStack().peek()).getList().get(1).getMap().get("key21") %><br>         --------------------------------------------<br>         <!-- 过滤 -->   person.name.lenth>2: <s:property value="list.{? #this.name.length()>2}"/><br>      person.iterator:<br>   <s:iterator value="list.{? #this.name.length()>2}">   <s:property value="name"/><br>   <s:property value="cat.name"/><br>   <s:property value="friends[0]"/><br><br>   </s:iterator>      <!-- 投影 -->   persons.name: <s:property value="list.{name}"/><br>      <s:iterator value="list.{name}">   <s:property/><br><!-- 这里已经是简单的属性了,不用写value,就可以取出来值了 -->   </s:iterator>     </body></html>