el 表达式 和 ognl表达式
el (expression language)
el 基础操作符
el 能够隐含对象(就是可以直接访问的)
el 的两种使用方式,第二种好像在jsp中没有什么用,主要用于jsf
el能够访问的对象(javaBean , 类集, 枚举 , 隐含对象)
在oracle官方网站上记录下来的一些我认为有用的东西:
1.
${customer}
The web container evaluates the variable that appears in an expression by looking up its value according to the behavior of PageContext.findAttribute(String), where the String argument is the name of the variable. For example, when evaluating the expression ${customer}, the container will look for customer in the page, request, session, and application scopes and will return its value. If customer is not found, a null value is returned.
web容器在处理这段代码是后台使用的是 PageContext.findAttribute(String)方法,该方法的定义如下:
该方法是抽象类PageContext继承抽象类JspContext的。
这个方法的定义和上面红色字体的描述基本相同,就是说会按照page -> request -> session -> application 的这个顺序搜寻customer属性,如果有返回,否者返回null。
2.
Where Value Expressions Can Be Used
Value expressions using the ${} delimiters can be used in
Static text
Any standard or custom tag attribute that can accept an expression
The value of an expression in static text is computed and inserted into the current output. Here is an example of an expression embedded in static text:
<some:tag>
some text ${expr} some text
</some:tag>
If the static text appears in a tag body, note that an expression will not be evaluated if the body is declared to be tagdependent.
Lvalue expressions can be used only in tag attributes that can accept lvalue expressions.
A tag attribute value using either an rvalue or lvalue expression can be set in the following ways:
With a single expression construct:
<some:tag value="${expr}"/>
<another:tag value="#{expr}"/>
These expressions are evaluated, and the result is converted to the attribute’s expected type.
With one or more expressions separated or surrounded by text:
<some:tag value="some${expr}${expr}text${expr}"/>
<another:tag value="some#{expr}#{expr}text#{expr}"/>
These kinds of expression, called composite expressions, are evaluated from left to right. Each expression embedded in the composite expression is converted to a String and then concatenated with any intervening text. The resulting String is then converted to the attribute’s expected type.
只看有颜色的字, 第一个说el可以再普通文本和作为标签的值使用,第二个和第三个颜色字分别为在普通文本和作为标签属性的实例。第四个表示el可以和文字任何搭配使用,其中的#我还不知道在jsp中有什么用。
ognl
1. 主要讲了ognl的调用链,该调用链只能用于get值,不能set值。
The fundamental unit of an OGNL expression is the navigation chain, usually just called "chain."
name.toCharArray()[0].numericValue.toString()
Note that this example can only be used to get a value
2. ognl不能使用setValue()这样会导致InappropriateExpressionException 异常抛出
from an object, not to set a value.Passing the above expression to the Ognl.setValue() method would cause an InappropriateExpressionException to be thrown, because the last link in the chain is neither a property name nor an array index.
3. ognl 的几种属性调用方式
For example, OGNL internally treats the "array.length" expression exactly the same as this expression: array["length"] And this expression would have the same result (though not the same internal form): array["len" + "gth"]
4. ognl同时可以调用方法,当然前提是该方法在ognl中,方法参数用逗号隔开。
5. 在逗号后面加上括号,在括号中可以对前面的对象值进行引用,例如下面的这个例子,#this表示listeners.size()的值。
listeners.size().(#this > 100? 2*#this : 20+#this)
5. 对变量赋值,与Java类似,如下例,#应该和不同范围的变量有关
To assign a value to a variable explicitly, simply write an assignment statement with a variable reference on the left-hand side:
#var = 99
6. 使用括号改变计算次序以及封装计算单元,方法类似于Java
Parenthetical Expressions As you would expect, an expression enclosed in parentheses is evaluated as a unit, separately from any surrounding operators. This can be used to force an evaluation order different from the one that would be implied by OGNL operator precedences. It is also the only way to use the comma operator in a method argument.
7. 在逗号后面使用括号,下面的这段代码会先搜寻headline.parent属性,然后执行ensureLoaded()方法,然后返回parent属性的name属性值
headline.parent.(ensureLoaded(), name)
traverses through the headline and parent properties,ensures that the parent is loaded and then returns (or sets) the parent's name.
8. 直接使用逗号,不使用括号的计算次序,下面这段代码和上面的类似,不过估计使用了默认的对象作为上下文
Top-level expressions can also be chained in this way.The result of the expression is the right-most expression element.
ensureLoaded(), name
This will call ensureLoaded() on the root object, then get the name property of the root object as the result of the expression.
9. 使用花括号定义list对象,下面这个表达式是用于判断name是不是等于null或者Untitiled,我猜测应该是先将name封装成list
name in { null,"Untitled" }
10. ognl定义原始类型的数组
new int[] { 1, 2, 3 }
new int[5]
11. 定义map
#{ "foo" : "foo value", "bar" : "bar value" }
12. 使用ognl遍历Collection类型的对象,其中的objects表示一个类集对象, #this表示遍历的当前元素,然后按照表达式对每一个元素进行计算,然后返回计算后得到的list元素,这在ognl官网上叫做projecting
objects.{ #this instanceof String ? #this :#this.toString()}
13. 使用ognl从类集对象中抽取出部分元素,这在ognl官方网站上叫做selection ,下面这个表达式从listeners类集对象中抽取出那些是ActionListener的元素
listeners.{? #this instanceof ActionListener}
使用ognl从类集对象中筛选出第一个符合的对象,然后将该对象封装成List返回,原始的做法是listeners.{? true }[0],但是这种方法是cumbersome(笨拙的),因为如果没有匹配到任何结果或者listeners.{? true}是空的,那么会抛出ArrayIndexOutOfBoundsException异常。使用下面这种格式会将第一个匹配的元素作为一个list对象返回,如果没有匹配到任何元素则会返回一个空list。
objects.{^ #this instanceof String }
14. 相同获取最后一个匹配的元素
objects.{$ #this instanceof String }
15. 使用ognl调用构造方法必须使用类的全名
You can create new objects as in Java, with the new operator. One difference is that you must specify the fully qualified class name for classes other than those in the java.lang package.
16. 使用ognl调用静态方法,这个leave out class 是什么意思?
If you leave out class, it defaults to java.lang.Math,to make it easier to call min and max methods. If you specify the class, you must give the fully qualified
name.
@class@method(args)
17. 获取静态属性
@class@field
18. 表达式的计算,下面这个表达式会将30作为BigInteger放入root对象(应该是value stack)中
#fact(30H)
19. 伪Lambda表达式(Pseudo-Lambda Expressions)
#fact = :[#this<=1? 1 : #this*#fact(#this-1)], #fact(30H)
The lambda expression is everything inside the brackets. The #this variable holds the argument to the expression, which is initially 30H, and is then one less for each successive call to the expression.
lambda表达式的所有内容都在一对方括号中,#this变量为lambda传递进参数fact的值,这个fact的值在后面进行了初始化为30H。
20. Connection 的伪属性
21. 在标点符号上与Java的不同
,(comma)
逗号用于分开两个独立的表达式,逗号后面的那个值是该逗号表达式的返回值。比如ensureLoaded(), name
{}(curly braces)
用于创建list对象,比如{ null, true, false }
in/not in
判断值是否属于某个集合,例如name in {null,"Untitled"} || name
22. ognl能够执行隐式的强制类型转换,具体规则如下:
Interpreting Objects as Booleans
Any object can be used where a boolean is required. OGNL interprets objects as booleans like this:
1) If the object is a Boolean, its value is extracted and returned;
2) If the object is a Number, its double-precision floating-point value is compared with zero; non-zero is treated as true, zero as false;
3) If the object is a Character, its boolean value is true if and only if its char value is non-zero;
Otherwise, its boolean value is true if and only if it is non-null.
Interpreting Objects as Numbers
Numerical operators try to treat their arguments as numbers. The basic primitive-type wrapper classes (Integer, Double, and so on, including Character and Boolean, which are treated as integers), and the "big" numeric classes from the java.math package (BigInteger and BigDecimal), are recognized as special numeric types. Given an object of some other class, OGNL tries to parse the object's string value as a number.Numerical operators that take two arguments use the following algorithm to decide what type the result should be. The type of the actual result may be wider, if the result does not fit in the given type.
1) If both arguments are of the same type, the result will be of the same type if possible;
2) If either argument is not of a recognized numeric class, it will be treated as if it was a Double for the rest of this algorithm;
3) If both arguments are approximations to real numbers (Float, Double, or BigDecimal), the result will be the wider type;
4) If both arguments are integers (Boolean, Byte, Character, Short, Integer, Long, or BigInteger), the result will be the wider type;
5) If one argument is a real type and the other an integer type, the result will be the real type if the integer is narrower than "int"; BigDecimal if the integer is BigInteger; or the wider of the real type and Double otherwise.
Interpreting Objects as Integers
Operators that work only on integers, like the bit-shifting operators, treat their arguments as numbers, except that BigDecimals and BigIntegers are operated on as BigIntegers and all other kinds of numbers are operated on as Longs. For the BigInteger case, the result of these operators remains a BigInteger; for the Long case, the result is expressed as the same type of the arguments, if it fits, or as a Long otherwise.
Interpreting Objects as Collections
The projection and selection operators (e1.{e2} and e1.{?e2}), and the in operator, all treat one of their arguments as a collection and walk it. This is done differently depending on the class of the argument:
1) Java arrays are walked from front to back;
2) Members of java.util.Collection are walked by walking their iterators;
3) Members of java.util.Map are walked by walking iterators over their values;
4) Members of java.util.Iterator and java.util.Enumeration are walked by iterating them;
5) Members of java.lang.Number are "walked" by returning integers less than the given number starting with zero;
All other objects are treated as singleton collections containing only themselves.
文章来源 http://commons.apache.org/proper/commons-ognl/language-guide.html
上面讲的都是ognl的一些特性,下面说一说都在哪些地方使用
The normal usage of OGNL is to embed the language inside of other constructs to provide a place for flexible binding of values from one place to another. An example of this is a web application where values need to be bound from a model of some sort to data transfer objects that are operated on by a view. Another example is an XML configuration file wherein values are generated via expressions which are then bound to configured objects.
上面这段话来自于ognl官方网站,主要是说ognl主要用于view(jsp)中,还有就是嵌入XML文件中,比如在web项目中的web.xml 和 strut中的struts.xml
关于ognl的使用
http://blog.csdn.net/li_tengfei/article/details/6098134。// 详细讲解valueStack,以及Ognl语言特性
http://www.blogjava.net/max/archive/2007/04/28/114417.html // Ognl的应用
这两篇博客讲的很清楚,我补充一个valueStack中对象的压人顺序: