Struts2之OGNL表达式与值栈对象及常用标签的使用

来源:互联网 发布:linux snmp 监控软件 编辑:程序博客网 时间:2024/05/16 08:58

一,概述

OGNL表达式

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目.Struts2使用OGNL作为默认的表达式语言.

OGNL优势

1)支持对象方法调用,如xxx.doSomeSpecial().
2)支持类静态的方法调用和值访问,表达式的格式:@[类全名(包括包路径)]@[方法名 |  值名],

例如:
             @java.lang.String@format('foo %s', 'bar')
             或@tutorial.MyConstant@APP_NAME
3)支持赋值操作和表达式串联,如price=100, discount=0.8,calculatePrice(),这个表达式会返回80.
4)访问OGNL上下文(OGNL context)和ActionContext;
5)操作集合对象.

总结

OGNL有一个上下文(OgnlContext)概念,其实它的上下文就是map结构,它实现了java.utils.Map接口.

public class OgnlContext extends Object implements Map{...}

二,OGNL的API类和方法

OgnlContext类(本质上是一个Map)

硬编码方式了解OgnlContext对象

1)Ognl表达式语言取值,取非根元素的值,必须用#号

/** * Ognl表达式语言取值,取非根元素的值,必须用#号 * @throws Exception */@Testpublic void testOgnl() throws Exception {OgnlContext context=new OgnlContext();User user=new User();user.setId(111);user.setName("张国荣");//存context.put("Leslie", "哥哥");//往非根元素放入数据,取值的时候要用#context.put("user", user);//拿数据:通过map//通过Ognl表达式取数据Object ognl = Ognl.parseExpression("#Leslie");//Object ognl = Ognl.parseExpression("#user.name");Object value = Ognl.getValue(ognl, context, context.getRoot());System.out.println(value);}

2)Ognl表达式语言取值,取根元素的值,不用#号

@Testpublic void testOgnl2() throws Exception {OgnlContext context=new OgnlContext();User user=new User();user.setId(111);user.setName("张国荣--哥哥");//往非根元素放入数据,取值的时候要用#context.setRoot(user);//往根元素中放入数据,取值时直接用属性即可//拿数据:通过map//先构建一个ognl表达式,再解析表达式,通过Ognl表达式取数据Object ognl = Ognl.parseExpression("name");Object value = Ognl.getValue(ognl, context, context.getRoot());System.out.println(value);}

3)Ognl对静态方法调用的支持

@Testpublic void testOgnl3() throws Exception {OgnlContext context=new OgnlContext();//Object ognl = Ognl.parseExpression("@Math@floor(11.5)");//由于Math类比较常用,设计的比较特殊,所以可以这样写Object ognl = Ognl.parseExpression("@@floor(18.5)");Object value = Ognl.getValue(ognl, context, context.getRoot());System.out.println(value);}

三,ValueStack对象

1) ValueStack实际是一个接口,在Struts2中使用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2使用OGNL的基础.

public interface ValueStack {...}
2)ValueStack特点:ValueStack贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的request请求属性中,传入到jsp页面.
3)开发者只需要通过ActionContext对象就可以访问struts的其他的关键对象.(ActionContext是给开发者用的,便于学习与使用)

4) 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

ValueStack数据:



root=CompoundRoot表示的根元素数据,里面存放当前Action对象,成员变量(要提供相应的setter与getter方法才能通过<s:debug></s:debug>标签看到成员变量信息)等等.

context=OgnlContext主要就是存储一些域数据.

5)获取值栈ValueStack的两种方式,在同一个Action中不同方式拿到的值栈对象是相同的.

private void vs() throws Exception {//获取值栈对象:方式一HttpServletRequest request = ServletActionContext.getRequest();ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");//获得值栈对象:方式二ActionContext ac = ActionContext.getContext();ValueStack vs2 = ac.getValueStack();System.out.println(vs1 == vs2);//輸出:true}}

四,struts标签(使用了OGNL表达式语言)

1)存数据

package cn.bighuan.b_ognl;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.util.ValueStack;/** * struts的数据流转 * @author bighuan * */public class OgnlAction extends ActionSupport{//Action全局成员都是根元素的值private User user=new User(11,"Leslie");public void setUser(User user) {this.user = user;}public User getUser() {return user;}@Overridepublic String execute() throws Exception {ActionContext ac = ActionContext.getContext();//这两种存数据的方式有点不一样Map<String, Object> request = ac.getContextMap();request.put("request_data","request_data");Map<String ,Object> request1 = (Map<String, Object>) ac.get("request");request1.put("request_data111","request_data111");Map<String, Object> session = ac.getSession();Map<String, Object> application = ac.getApplication();request.put("request_data","request_data");session.put("session_data", "session_data");application.put("application_data", "application_data");ValueStack vs = ac.getValueStack();System.out.println(vs);return SUCCESS;}
2)jsp页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib uri="/struts-tags" prefix="s"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>        <title>My JSP 'index.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  </head>    <body>    <%--页面必须要拿到ValueStack --%>    <h3>取根元素的值 </h3>    <s:property value="user.name"/><br/>    <s:property value="user.id"/><br/>        <hr/>    <h3>取非根元素的值  </h3>    <s:property value="#request.request_data"/><br/>      <s:property value="#session.session_data"/><br/>       <s:property value="#application.application_data"/><br/>              <%--自动找request-->session-->application --%>        <h5>取非根元素的值 :通过attr取数据 </h5>       <s:property value="#attr.request_data"/><br/>        <s:property value="#attr.session_data"/><br/>         <s:property value="#attr.application_data"/><br/>              <hr/>        <h3>直接通过key取值  </h3>       ********Map<String, Object> request = ac.getContextMap();两种方式取值******************<br/>       <s:property value="#request_data"/><br/>        <s:property value="#request.request_data"/><br/>       ***Map<String ,Object> request1 = (Map<String, Object>) ac.get("request");只有一种方式****<br/>       <%--  <s:property value="#request_data111"/><br/>错误 --%>       <s:property value="#request.request_data111"/><br/>         <s:property value="user.name"/><br/><br/>               <br/>*******************重要点**********************            <hr>通过get("request")得到map对象得到的数据,这种方式只能通过#+域+key取值</hr><br/>         <s:property value="#request.request_data111"/>            <%--调试标签 --%>    <s:debug></s:debug>  </body></html>
3_存List数据或Map数据

package cn.bighuan.b_ognl;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.util.ValueStack;public class OgnlDemo3 extends ActionSupport{@Overridepublic String execute() throws Exception {//迭代标签List<User> list = new ArrayList<User>();Map<Integer,User> map = new HashMap<Integer, User>();// 初始化for (int i=0; i<10; i++) {User user = new User(i,"Leslie" + i);list.add(user);map.put(user.getId(), user);}// 保存 ActionContext.getContext().getContextMap().put("list", list);ActionContext.getContext().getContextMap().put("map", map);return super.execute();}}

4)迭代器标签

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib uri="/struts-tags" prefix="s"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>My JSP 'ognl_tag.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><style type="text/css" >   .odd{           background-color: red;           }   .even{           background-color:blue;}  </style></head><body><br />一、. list迭代</br><table border="1"><tr><td>编号</td><td>名称</td></tr><s:iterator var="user" value="#request.list" status="st"><tr class=<s:property value="#st.even?'even':'odd'"/>><td><s:property value="#user.id" /></td><td><s:property value="#user.name" /></td></tr></s:iterator></table><br />二、迭代map</br><table border="1"><tr><td>编号</td><td>名称</td></tr><s:iterator var="en" value="#request.map" status="st"><tr><td><s:property value="#en.key" /></td><td><s:property value="#en.value.name" /></td></tr></s:iterator></table><!-- Ognl表达式可以取值,也可以动态构建集合 --></body></html>

五,ValueStack总结

1)值栈以struts.valueStack的名字存储在request请求中,值栈主要包含两个栈:对象栈和Map栈.
        对象栈存储的是用户的基本数据和对象数据 ; Map栈主要存储的是域对象属性。
        用户每次一个请求就一个Action实例,对应一个值栈对象。
2)思考:
       放在request中的值栈中可以存储session和servletContext域数据,显然request的作用有没有那么大?直接使用拷贝的方式以key=value的方式拷贝到Map栈对应的Map中.
Map栈中的_root
       debug可见该属性中引用的是对象栈数据。如果在Map栈中不存储_root对于对象栈的引用,那么开发者需要访问数据时候首先要区分是访问对象栈还是Map栈,比较繁琐。因此以后操作数据直接操作Map栈即可。



0 0