`

Struts2 ValueStack & ActionContext & OGNL 关系

 
阅读更多

1.原生的OGNL

 1) Introduction

  OGNL stands for Object-Graph Navigation Language; it is an expression language for getting and setting properties of Java objects, plus other extras such as list projection and selection and lambda expressions. You use the same expression for both getting and setting the value of a property.

  We pronounce OGNL as a word, like the last syllables of a drunken pronunciation of "orthogonal".

  Many people have asked exactly whatOGNLis good for. Several of the uses to whichOGNLhas been applied are:

  • A binding language between GUI elements (textfield, combobox, etc.) to model objects. Transformations are made easier byOGNL's TypeConverter mechanism to convert values from one type to another (String to numeric types, for example);
  • A data source language to map between table columns and a Swing TableModel;
  • A binding language between web components and the underlying model objects;
  • A more expressive replacement for the property-getting language used by the Apache Commons BeanUtils package or JSTL's EL (which only allow simple property navigation and rudimentary indexed properties).

  OGNL常被用来做为View与Model之间的胶水语言,在View中方便的使用Model对象,OGNL负责收集这些Model对象,在View中使用简单的OGNL表达式,就可以取到想要的对象。既消除了在View中直接使用getters 和 setters的重复代码的书写,还避免了在View代码中写的强制类型转换(Cast)。

  表达式语言(EL)本质上被设计为:帮助你使用简单的表达式来完成一些“常用”的工作。通常情况下,ELs 可以在一些框架中找到,它被是用来简化我们的工作。例如:大家熟知的 Hibernate,使用 HQL(Hibernate Query Language) 来完成数据库的操作,HQL 成了开发人员与复查的 SQL 表达式之间的一个桥梁。 在 web 框架下,表达式语言起到了相似的目的。它的存在消除了重复代码的书写。

 2) Use OGNL

staticObject getValue(Objecttree,Mapcontext,Objectroot)
Evaluates the given OGNL expression tree to extract a value from the given root object.
staticObject getValue(Objecttree,Mapcontext,Objectroot,ClassresultType)
Evaluates the given OGNL expression tree to extract a value from the given root object.
staticObject getValue(Objecttree,Objectroot)
Evaluates the given OGNL expression tree to extract a value from the given root object.
staticObject getValue(Objecttree,Objectroot,ClassresultType)
Evaluates the given OGNL expression tree to extract a value from the given root object.
staticObject getValue(Stringexpression,Mapcontext,Objectroot)
Evaluates the given OGNL expression to extract a value from the given root object in a given context
staticObject getValue(Stringexpression,Mapcontext,Objectroot,ClassresultType)
Evaluates the given OGNL expression to extract a value from the given root object in a given context
staticObject getValue(Stringexpression,Objectroot)
Convenience method that combines calls toparseExpressionandgetValue.
staticObject getValue(Stringexpression,Objectroot,ClassresultType)
Convenience method that combines calls toparseExpressionandgetValue.

  使用OGNL非常简单,我们只用到了Ognl.jar文件,并且只使用了其中的一个类ognl.Ognl。这个类中的方法都是静态static方法。取值只用到了getValue方法,这个方法是个重载overload方法。

  OGNL三要素:

  1.expression 求值表达式——首先会被解析成对象树

  2.root object 根对象——默认的操作对象

  3.context OGNL执行环境——OGNL执行的上下文环境

  OGNL context是一个Map结构,ognl.OgnlContext类implements Map接口,root对象也在context里面,并且做这一个特殊的对象处理,具体表现为对root 对象的操作不需要加#指示符号(并且加上了#一定取不到root对象里面的值)。

  看一个例子:

Person类:

复制代码
 1 package com.cuillgln.ognl;
 2 
 3 public class Person {
 4     private String name;
 5     private int age;
 6     private String telphone;
 7 
 8     public Person() {
 9 
10     }
11 
12     public Person(String name, int age, String telphone) {
13         this.name = name;
14         this.age = age;
15         this.telphone = telphone;
16     }
17 
18     public String getName() {
19         return name;
20     }
21 
22     public void setName(String name) {
23         this.name = name;
24     }
25 
26     public int getAge() {
27         return age;
28     }
29 
30     public void setAge(int age) {
31         this.age = age;
32     }
33 
34     public String getTelphone() {
35         return telphone;
36     }
37 
38     public void setTelphone(String telphone) {
39         this.telphone = telphone;
40     }
41 
42 }
复制代码

OgnlTest类:

复制代码
  1 package com.cuillgln.ognl;
  2 
  3 import ognl.Ognl;
  4 import ognl.OgnlContext;
  5 import ognl.OgnlException;
  6 
  7 public class OgnlTest {
  8 
  9     public static void main(String[] args) {
 10         try {
 11             OgnlContext context = new OgnlContext();
 12             context.put("name", "STRING1~~~");
 13             context.put("age", 100);
 14             context.put("telphone", "STRING3~~~");
 15             context.put("person.name", "STRING4~~~");
 16 
 17             Person p1 = new Person("Lee", 12, "134xxxxxxxx");
 18             Person p2 = new Person("Zhang", 15, "150xxxxxxxx");
 19             Person p3 = new Person("Wang", 18, "186xxxxxxxx");
 20             
 21             context.put("person1", p1);
 22             context.put("person2", p2);
 23             context.put("person3", p3);
 24             
 25             Person root = new Person("ROOT", 100, "xxxxxxxx");
 26 
 27             /*
 28              * the output is :
 29              * the value is: ROOT======
 30              * obviously, value是对应root object 的name属性的对象。
 31              * 输出的是这个对象的值
 32              */
 33             Object value = Ognl.getValue("name", context, root);
 34             System.out.println("the value is: " + value + "======");
 35             
 36             /*
 37              * the output is :
 38              * the value is: STRING1~~~======
 39              * obviously, value是context中,Key为name的对象
 40              * 输出的是这个对象的值
 41              */
 42             value = Ognl.getValue("#name", context, root);
 43             System.out.println("the value is: " + value + "======");
 44             
 45             /*
 46              * the output is :
 47              * ognl.NoSuchPropertyException: com.cuillgln.ognl.Person.person1
 48              * obviously, OGNL会试图去找root object中属性为person1的对象,
 49              * 结果没有找到,所以抛出ognl.NoSuchePropertyException
 50              */
 51             value = Ognl.getValue("person1", context, root);
 52             System.out.println("the value is: " + value + "======");
 53             
 54             /*
 55              * the output is :
 56              * the value is: com.cuillgln.ognl.Person@7d8483======
 57              * obviously, value是context中,Key为person1的对象。
 58              * 输出的结果是这个对象的toString的返回值
 59              */
 60             value = Ognl.getValue("#person1", context, root);
 61             System.out.println("the value is: " + value + "======");
 62             
 63             /*
 64              * the output is :
 65              * ognl.NoSuchPropertyException: com.cuillgln.ognl.Person.person1
 66              * obviously, OGNL会试图去找root object中属性为person1的对象,然后再找属性person1对应对象的name属性对应的对象
 67              * 结果没有找到root object中有person1属性对应的对象,
 68              * 所以抛出ognl.NoSuchePropertyException: com.cuillgln.ognl.Person.person1
 69              */
 70             value = Ognl.getValue("person1.name", context, root);
 71             System.out.println("the value is: " + value + "======");
 72             
 73             /*
 74              * the output is :
 75              * the value is: Lee======
 76              * obviously, OGNL会试图去找context中Key为person1对应的对象,再对这个对象取name属性对应的对象
 77              * 结果找到了正确输出了……。Lee
 78              */
 79             value = Ognl.getValue("#person1.name", context, root);
 80             System.out.println("the value is: " + value + "======");
 81             
 82             /*
 83              * the output is :
 84              * ognl.OgnlException: source is null for getProperty(null, "name")
 85              * obviously, OGNL会试图去找context中Key为person对应的对象,再对这个对象取name属性对应的对象
 86              * 结果在context中没有找到Key为person的属性,故返回null,在null上再取name属性,明显会出错。
 87              */
 88             value = Ognl.getValue("#person.name", context, root);
 89             System.out.println("the value is: " + value + "======");
 90             
 91             /*
 92              * the output is :
 93              * ognl.NoSuchPropertyException: java.lang.String.name
 94              * obviously, OGNL会试图在root object中查找name属性对应的对象,
 95              * 现在root object是一个String字符串,且没有name属性,故会抛出ognl.NoSuchPropertyException
 96              */
 97             value = Ognl.getValue("name", context, "abcdefg");
 98             System.out.println("the value is: " + value + "======");
 99             
100             /*
101              * the output is :
102              * the value is: STRING1~~~======
103              * obviously, value是context中,Key为name的对象,跟root object没有关系
104              * 输出的是这个对象的值
105              */
106             value = Ognl.getValue("#name", context, "abcdefg");
107             System.out.println("the value is: " + value + "======");
108             
109         } catch (OgnlException e) {
110             // TODO Auto-generated catch block
111             e.printStackTrace();
112         }
113     }
114 }
复制代码

  这些就是OGNL的基础知识,OGNL另外还有很强大的功能,包括投影、支持lambda表达式,暂不做介绍。

 2.XWork-specific OGNL features

  1)There can be many "root" objects.XWork中的表示根对象是CompoundRoot对象。CompoundRoot类extends ArrayList类。因为是一个List,里面可以放置多个对象,而这些对象经过XWork的改进对于OGNL表达式引擎来说都是root objects。XWork has a special OGNL PropertyAccessor that will automatically look at the all entries in the stack (in fact the CompoundRoot list) (from the top down) until it finds an object with the property you are looking for.

  2)Struts2 Named Objects

  Struts 2 places request parameters and request, session, and application attributes on the OGNL stack(in fact the OGNL context). They may be accessed as shown below.

name value
#parameters['foo'] or #parameters.foo request parameter ['foo'] (request.getParameter())
#request['foo'] or #request.foo request attribute ['foo'] (request.getAttribute())
#session['foo'] or #session.foo session attribute 'foo'
#application['foo'] or #application.foo ServletContext attributes 'foo'
#attr['foo'] or #attr.foo Access to PageContext if available, otherwise searches request/session/application respectively

 以OGNL表达式的观点来对上述两点做出解释:

  1)的意思是:OGNL中的root object,现在是CompoundRoot对象,CompoundRoot对象并不直接在里面放置属性(指JavaBean中的Field),而是一些对象列表。如果要用原生的OGNL表达式获取里面某个对象的值,会出现什么状况?你会发现根本取不到里面的对象。如下面的代码抛出的异常:ognl.NoSuchPropertyException: java.util.ArrayList.person。所以XWork在使用OGNL前做了一些特殊处理,具体就是使用了一个特殊的PropertyAccessor来访问CompoundRoot里面的对象。(具体没有研究……)

复制代码
 1             Person p1 = new Person("Lee", 12, "134xxxxxxxx");
 2             Person p2 = new Person("Zhang", 15, "150xxxxxxxx");
 3             Person p3 = new Person("Wang", 18, "186xxxxxxxx");
 4 
 5             context.put("person1", p1);
 6             context.put("person2", p2);
 7             context.put("person3", p3);
 8 
 9             List<Object> root = new ArrayList<Object>();
10             root.add(p3);
11             root.add(p2);
12             root.add(p1);
13             /*
14              * the output is : 
15              * ognl.NoSuchPropertyException: java.util.ArrayList.person
16              * 你会发现很难用表达式,表达出来你要查找的对象(导航到你要找的对象)————无解……
17              */
18             Object value = Ognl.getValue("person.name", context, root);
19             System.out.println("the value is: " + value + "======");
复制代码

  2)的意思是:Struts把跟Web相关的对象,具体就是request parameters, request attributes, session attributes, application attributes。放在OGNL的context中,分别对应parameters, request, session, application的Key。attributes都以Key/Value的形式存在的,所以在OGNL context里key等于parameters, request, session, application的Value对应的对象类型是一个Map类。

3.OgnlValueStack的结构

  OgnlValueStack类implements ValueStack接口。里面有两个Field: context和root,分别是OGNL的两大要素OGNL context 和root object。

复制代码
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
    CompoundRoot root;
    transient Map<String, Object> context;
    Class defaultType;
   transient OgnlUtil ognlUtil;
   protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot,
                           boolean allowStaticMethodAccess) {
        this.root = compoundRoot;
        this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess);
        this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess);
        context.put(VALUE_STACK, this);
        Ognl.setClassResolver(context, accessor);
        ((OgnlContext) context).setTraceEvaluations(false);
        ((OgnlContext) context).setKeepLastEvaluation(false);
    }
/**
     * @see com.opensymphony.xwork2.util.ValueStack#getContext()
     */
    public Map<String, Object> getContext() {
        return context;
    }
/**
     * @see com.opensymphony.xwork2.util.ValueStack#getRoot()
     */
    public CompoundRoot getRoot() {
        return root;
    }
/**
     * @see com.opensymphony.xwork2.util.ValueStack#findString(java.lang.String)
     */
    public String findString(String expr) {
        return (String) findValue(expr, String.class);
    }

    public String findString(String expr, boolean throwExceptionOnFailure) {
        return (String) findValue(expr, String.class, throwExceptionOnFailure);
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#findValue(java.lang.String)
     */
    public Object findValue(String expr, boolean throwExceptionOnFailure) {
        try {
            setupExceptionOnFailure(throwExceptionOnFailure);
            return tryFindValueWhenExpressionIsNotNull(expr);
        } catch (OgnlException e) {
            return handleOgnlException(expr, throwExceptionOnFailure, e);
        } catch (Exception e) {
            return handleOtherException(expr, throwExceptionOnFailure, e);
        } finally {
            ReflectionContextState.clear(context);
        }
    }

private Object tryFindValueWhenExpressionIsNotNull(String expr) throws OgnlException {
        if (expr == null) {
            return null;
        }
        return tryFindValue(expr);
    }

private Object tryFindValue(String expr) throws OgnlException {
        Object value;
        expr = lookupForOverrides(expr);
        if (defaultType != null) {
            value = findValue(expr, defaultType);
        } else {
            value = getValueUsingOgnl(expr);
            if (value == null) {
                value = findInContext(expr);
            }
        }
        return value;
    }

private Object getValueUsingOgnl(String expr) throws OgnlException {
        try {
            return ognlUtil.getValue(expr, context, root);
        } finally {
            context.remove(THROW_EXCEPTION_ON_FAILURE);
        }
    }

    public Object findValue(String expr) {
        return findValue(expr, false);
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#findValue(java.lang.String, java.lang.Class)
     */
    public Object findValue(String expr, Class asType, boolean throwExceptionOnFailure) {
        try {
            setupExceptionOnFailure(throwExceptionOnFailure);
            return tryFindValueWhenExpressionIsNotNull(expr, asType);
        } catch (OgnlException e) {
            return handleOgnlException(expr, throwExceptionOnFailure, e);
        } catch (Exception e) {
            return handleOtherException(expr, throwExceptionOnFailure, e);
        } finally {
            ReflectionContextState.clear(context);
        }
    }

    private Object tryFindValueWhenExpressionIsNotNull(String expr, Class asType) throws OgnlException {
        if (expr == null) {
            return null;
        }
        return tryFindValue(expr, asType);
    }

    private Object handleOgnlException(String expr, boolean throwExceptionOnFailure, OgnlException e) {
        Object ret = findInContext(expr);
        if (ret == null) {
            if (shouldLogNoSuchPropertyWarning(e)) {
                LOG.warn("Could not find property [" + ((NoSuchPropertyException) e).getName() + "]");
            }
            if (throwExceptionOnFailure) {
                throw new XWorkException(e);
            }
        }
        return ret;
    }
private Object tryFindValue(String expr, Class asType) throws OgnlException {
        Object value = null;
        try {
            expr = lookupForOverrides(expr);
            value = getValue(expr, asType);
            if (value == null) {
                value = findInContext(expr);
            }
        } finally {
            context.remove(THROW_EXCEPTION_ON_FAILURE);
        }
        return value;
    }

private Object findInContext(String name) {
        return getContext().get(name);
    }

    public Object findValue(String expr, Class asType) {
        return findValue(expr, asType, false);
    }

  private Object getValue(String expr, Class asType) throws OgnlException {
    return ognlUtil.getValue(expr, context, root, asType);
  }

/**
     * @see com.opensymphony.xwork2.util.ValueStack#peek()
     */
    public Object peek() {
        return root.peek();
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#pop()
     */
    public Object pop() {
        return root.pop();
    }

    /**
     * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object)
     */
    public void push(Object o) {
        root.push(o);
    }

  public void set(String key, Object o) {
    //set basically is backed by a Map pushed on the stack with a key being put on the map and the Object being the value
    Map setMap = retrieveSetMap();
    setMap.put(key, o);
  }


  private Map retrieveSetMap() {     Map setMap;     Object topObj = peek();     if (shouldUseOldMap(topObj)) {       setMap = (Map) topObj;     } else {       setMap = new HashMap();       setMap.put(MAP_IDENTIFIER_KEY, "");       push(setMap);//放在了CompoundRoot的顶部     }     return setMap;   }

  /**   * check if this is a Map put on the stack for setting if so just use the old map (reduces waste)   */   private boolean shouldUseOldMap(Object topObj) {     return topObj instanceof Map && ((Map) topObj).get(MAP_IDENTIFIER_KEY) != null;   }

}
复制代码

  从源码中可以看出:

  1)对ValueStack的栈操作(即peek、pop、push)实际上是对root上的操作。————这就是为什么说有时候ValueStack特指Object Stack。这里的Object Stack即是CompoundRoot对象,它提供了对栈的操作接口。

  2)findValue的过程:经过一系列的方法,最后调用tryFindValue方法,tryFindValue首先调用getValue,getValue调用OgnlUtil.getValue,OgnlUtil.getValue调用原生OGNL的Ognl.getValue方法。如果得到的value是null,会再调用findInContext方法,findInContext返回getContext().get(name),这是试图从context里获得Key为name的Value值。这是的name可能很复杂,如"person.name",此时不会再被解释成“先取得属性名为person的对象,再取这个对象的name属性对应的对象”,而是直接做为Map.get()里的一个Key。

  3)ValueStack.set(String key, Object value);确实是在CompoundRoot栈顶压入了一个HashMap,里面放入了set的Key/value pairs。

4.ActionContext类结构及初始化过程

  ActionContext里只有一个Filed,即context。从FilterDispacher的doFilter方法中,可以看出,ActionContext中的context被初始化为ValueStack中context的内容。并且在后面又在context中添加了一些key/value pairs。主要是把从ValueStack的context中的request parameters, request attributes, session attributes, application attributes,又以不同的Key放在了context中。并且还把整个ValueStack对象也放到了context中,Key是 "com.opensymphony.xwork2.util.ValueStack.ValueStack"。并且提供了这些对象的setters/getters方法。

复制代码
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
                 throws IOException, ServletException { 
     HttpServletRequest request = (HttpServletRequest) req; 
     HttpServletResponse response = (HttpServletResponse) res; 
     ServletContext servletContext = getServletContext(); 

     String timerKey = "FilterDispatcher_doFilter: "; 
     try { 
          //1 处理前的准备
          //1.1 创建值栈对象,值栈包含 object stack 和 context map 两个部分。
      ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack(); 
          //1.2 创建 actionContext。
         ActionContext ctx = new ActionContext(stack.getContext()); 
         ActionContext.setContext(ctx); 

// 省略剩余代码
复制代码

5.use Struts tags with OGNL expression

  自定义标签(Customer Tags)一般都继承自javax.servlet.jsp.tagext.BodyTagSupport类,重写(overriding)doStartTag()和doEndTag()方法。

  对于像<s:set var="test" value="%{'abc'}" scope="scope"/>assigns a value to a variable in a specified scope。根据源代码可以看出来实际上是把var定义的key放到了context中相应的scope下的Map中或context中。调用的是ValueStack.setValue(expr, Object)方法,而不是ValueStac.set(key, value)方法。两方法的区别:

  1)ValueStac.set(key, value)是在CompoundRoot栈顶压入了一个HashMap,里面放入了set的Key/value pairs。

  2)ValueStack.setValue(expr, object)是给根据expr查找到的对象赋与object值。

  这就可以理解为什么在用<s:set/>绑定一个变量后,一般还是要加#才能取到值的原因了。因为他们的key/value pairs放置在context中,而不是CompoundRoot中。

  还要理解为什么有一部分变量就不用加#也可以取到。不加#可以取到条件有(三个条件,缺一不可):

    1) <s:set scope="action"/>中scope的值是默认值,即action作用域。

    2)<s:set value=""/>中value是个OGNL constants. 即String, 各种Number, Boolean, null等。

    3)在CompoundRoot对象中没有名为此key的属性。

  为什么能取到:

    1)scope="action"是把key/value pairs直接ValueStack.getContext().put(key, value)的。是存放在OGNL context中的。

    2)按原生的OGNL,不加#号是不可能取到的。

    3)Struts中的OgnlValueStack的tryFindValue()在用原生的OGNL getValue()得到的是null后(说明在CompoundRoot中没有与此key同名的属性),会调用findInContext(key)方法return getContext.get(key)。如此,如果在context中有此key,便可不用#也可能取到想要的值。

复制代码
 1 public boolean end(Writer writer, String body) {
 2         ValueStack stack = getStack();
 3 
 4         Object o;
 5         if (value == null) {
 6             if (body != null && !body.equals("")) {
 7                 o = body;
 8             } else {
 9                 o = findValue("top");
10             }
11         } else {
12             o = findValue(value);
13         }
14 
15         body="";
16 
17         if ("application".equalsIgnoreCase(scope)) {
18             stack.setValue("#application['" + getVar() + "']", o);
19         } else if ("session".equalsIgnoreCase(scope)) {
20             stack.setValue("#session['" + getVar() + "']", o);
21         } else if ("request".equalsIgnoreCase(scope)) {
22             stack.setValue("#request['" + getVar() + "']", o);
23         } else if ("page".equalsIgnoreCase(scope)) {
24             stack.setValue("#attr['" + getVar() + "']", o, false);
25         } else {
26             stack.getContext().put(getVar(), o);
27             stack.setValue("#attr['" + getVar() + "']", o, false);
28         }
29 
30         return super.end(writer, body);
31     }
分享到:
评论

相关推荐

    Struts中的ognl和valueStack

    深入讲解Struts中的ognl和valueStack

    Struts2中关于ValueStack的一些操作

    3、 WebWork的ValueStack底层有第三方开源项目OGNL实现。所以EL也都遵循OGNL的规范。我们在开发中,几乎不需要知道OGNL的细节。 4、 WebWork为每一次请求构建一个ValueStack,并将所有相关的数据对象(例如:...

    Struts用的ognl和valueStack(vs)实例

    Struts用的ognl和valueStack(vs)实例

    struts学习笔记(3)

    com.opensymphony.xwork2.ActionContext和com.opensymphony.xwork2.util.ValueStack 1)ValueStack和ActionContext的作用: 当客户端向action发送请求并且最后跳转到另外一个页面的时候,在跳转的同时,struts2框架...

    Struts2中的参数传递

    我们知道,Struts2完成参数传递处理工作的基础是OGNL和ValueStack。而在这个 过程中,我也把Struts2所要做的工作大致归纳为两个方面: 1. 对OGNL操作进行封装,完成OGNL表达式所表示的值到Java对象的值传递机制 2. ...

    s20505_valueStack_OGNL

    Struts2 demo,使用struts2的ognl表达式传值,以及页面的数据的实时的刷新。

    Struts2 in action中文版

    5.2 OGNL和Struts 2 85 5.2.1 OGNL是什么 85 5.2.2 OGNL如何融入框架 87 5.3 内建的类型转换器 89 5.3.1 立即可用的类型转换器 89 5.3.2 使用OGNL表达式从表单字段名映射到属性 90 5.4 自定义类型转换 101 5.4.1 ...

    linjin101#javaStudy#Struts2中的OGNL和值栈ValueStack1

    1、什么是值栈 2、值栈的内部结构 3、ActionContext和ValueStatck的关系 4、如何获取值栈对象 5、向值栈存数据 6、从值栈中获取数据

    马士兵Struts2笔记2013

    建立一个Struts2 工程,用Action的属性接收参数,使用Domain Model (实体模型) 接收参数,Struts2_2.1.6版本的中文问题,Struts模块包含,Struts简单数据验证 ,Struts ValueStack(值栈) Debug,Value Stack ...

    Struts2入门教程(全新完整版)

    四、OGNL与ValueStack(VS) 22 1.值栈入门 22 2.OGNL入门 24 3.普通方法访问 24 4.静态方法访问 24 5.默认类Math的访问 24 6.调用普通类的构造方法 25 7.集合对象初步 25 8.集合对象进阶 25 9.N语法top语法 26 10....

    OGNL表达归纳

    3.由于ValueStack(值栈)是Struts 2中OGNL的根对象,如果用户需要访问值栈中的对象,在JSP页面可以直接通过下面的EL表达式访问ValueStack(值栈)中对象的属性 4.为何使用EL表达式能够访问valueStack中对象的属性 原因...

    OGNL表达式语言.txt

    OGNL表达式语言: 相对EL表达式,它提供了平时我们需要的一些功能,如: ...另外OGNL会设定一个根对象(root对象),在Struts2中根对象是ValueStack。 如果访问根对象中的对象的属性,则可以省略#命名空间。

    struts项目调优需要的ognl2.7的jar包

    ognl2.7相对于2.6在性能上有了“显著”的提升.所以该jar包能对struts2的调优有很大帮助,尤其是ValueStack中的操作比较多的情况下。

    Struts2练习Demo以及随笔

    Struts的开发步骤、OGNL、ValueStack、Action核心、Result基本原理、Struts2核心标记库、Struts2拦截器、自定义拦截器、UI标记、非UI标记、资源文件国际化等等实例全面使用。

    Struts2 Value Stack Contents 中取值、多个集合数组

    Struts2 Value Stack Contents 中取值、多个集合数组示例

    Struts2框架基础 二

    OGNL表达式 interceptor拦截器 valuestack的存入 /取出

    struts2 学习例子

    Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,...

    struts2 标签库使用文档

    Struts2标签库的组成 Struts2框架的标签库可以分为以下三类: 用户界面标签(UI标签):主要用来生成HTML元素的标签。 表单标签:主要用于生成HTML页面的FORM元素,以及普通表单元素的标签。 非表单标签:主要用于生成...

    struts.docx

    Struts2是处理访问服务器的请求 学习struts2的(重点) Struts.xml的配置 参数传递 Ognl ValueStack Action原理 Result原理 拦截器 struts将会完全的取代我们的servlet技术

    xwork-sources

    struts2.0 ValueStack 相关源码

Global site tag (gtag.js) - Google Analytics