在EL表达式计算过程中,有朋友会遇到许多奇怪的问题,经常非常郁闷,在此我把这些总结一下,方便查询:
1、所有的整数数字字面量都是Long类型的;
2、所有小数字面量都是Double类型的;
3、""或''声明的是字符串,即''也是字符串,非char;
4、比较时都是equals比较。
接下来看几个可能出问题的例子,你会遇到一下的几个呢:
1、
如${1+2147483647
} 结果是多少?
如果在java程序里边运行会得到-2147483648,而在jsp el中会得到2147483648。
2、
<%
Map<Object, Object> map = new HashMap<Object, Object>();
map.put(new Long(1), 123);
request.setAttribute("map", map);
request.setAttribute("a", new Long(1));
%>
${map[1]} 正确
${map[a]} 正确
3、
<%
Map<Object, Object> map = new HashMap<Object, Object>();
map.put(new Integer(1), 123);
request.setAttribute("map", map);
request.setAttribute("a", new Long(1));
request.setAttribute("b", new Integer(1));
%>
${map[1]} 错误
${map[a]} 错误
${map[b]} 正确
4、
<%
Map<Object, Object> map = new HashMap<Object, Object>();
map.put(1.1, 123); //map.put(1.1d, 123);
request.setAttribute("map", map);
request.setAttribute("a", new Double(1.1));
%>
map.a=${map[1.1]} 正确
map.a=${map[a]} 正确
5、
<%
Map<Object, Object> map = new HashMap<Object, Object>();
map.put(1.1f, 123); //map.put(new Float(1.1), 123);
request.setAttribute("map", map);
request.setAttribute("a", new Double(1.1));
request.setAttribute("b", new Float(1.1));
%>
map.a=${map[1.1]} 错误
map.a=${map[a]} 错误
map.a=${map[b]} 正确
6、
结合struts2的ognl表达式
<s:property value="#map = #{'a':123, 'b':234}, ''"/> --->定义一个map,放入值栈的上下文区
<s:property value="#map['a']"/> ---------->正确,因为其支持char
${map['a']} ------------>错误, 因为'a'在jsp el表达式中是字符串,不能=char。
<s:property value='#map = #{"a":123, "b":234}, ""'/> --->此时key是字符串
${map['a']}
此处需要注意ognl中'×××' 如果长度是1那么是Character 否则是String 可参考
http://jinnianshilongnian.iteye.com/blog/1870662
补充:
在EL表达式规范2.2中,定义了:
Long.MAX_VALUE
■ The value of a FloatingPointLiteral ranges from Double.MIN_VALUE to
Double.MAX_VALUE
在tomcat7.0.6实现中,jasper.jar(实现了EL2.2规范):
AstFloatingPoint表示小数,AstInteger表示整数,其定义如下:
- public final class AstInteger extends SimpleNode
- {
- private volatile Number number;
- public AstInteger(int id)
- {
- super(id);
- }
- protected Number getInteger()
- {
- if (this.number == null) {
- try {
- this.number = new Long(this.image);
- } catch (ArithmeticException e1) {
- this.number = new BigInteger(this.image);
- }
- }
- return this.number;
- }
- public Class<?> getType(EvaluationContext ctx)
- throws ELException
- {
- return getInteger().getClass();
- }
- public Object getValue(EvaluationContext ctx)
- throws ELException
- {
- return getInteger();
- }
- }
- public final class AstFloatingPoint extends SimpleNode
- {
- private volatile Number number;
- public AstFloatingPoint(int id)
- {
- super(id);
- }
- public Number getFloatingPoint()
- {
- if (this.number == null) {
- try {
- this.number = new Double(this.image);
- } catch (ArithmeticException e0) {
- this.number = new BigDecimal(this.image);
- }
- }
- return this.number;
- }
- public Object getValue(EvaluationContext ctx)
- throws ELException
- {
- return getFloatingPoint();
- }
- public Class<?> getType(EvaluationContext ctx)
- throws ELException
- {
- return getFloatingPoint().getClass();
- }
- }
+ - * /实现,此处只看+的:
- package org.apache.el.parser;
- import javax.el.ELException;
- import org.apache.el.lang.ELArithmetic;
- import org.apache.el.lang.EvaluationContext;
- public final class AstPlus extends ArithmeticNode
- {
- public AstPlus(int id)
- {
- super(id);
- }
- public Object getValue(EvaluationContext ctx)
- throws ELException
- {
- Object obj0 = this.children[0].getValue(ctx);
- Object obj1 = this.children[1].getValue(ctx);
- return ELArithmetic.add(obj0, obj1);
- }
- }
其委托给ELArithmetic.add:
- public static final DoubleDelegate DOUBLE = new DoubleDelegate();
- public static final LongDelegate LONG = new LongDelegate();
- private static final Long ZERO = Long.valueOf(0L);
- public static final Number add(Object obj0, Object obj1) {
- if ((obj0 == null) && (obj1 == null))
- return Long.valueOf(0L);
- ELArithmetic delegate;
- if (BIGDECIMAL.matches(obj0, obj1))
- delegate = BIGDECIMAL;
- else if (DOUBLE.matches(obj0, obj1))
- if (BIGINTEGER.matches(obj0, obj1))
- delegate = BIGDECIMAL;
- else
- delegate = DOUBLE;
- else if (BIGINTEGER.matches(obj0, obj1))
- delegate = BIGINTEGER;
- else {
- delegate = LONG;
- }
- Number num0 = delegate.coerce(obj0);
- Number num1 = delegate.coerce(obj1);
- return delegate.add(num0, num1);
- }
此处委托给了各种delegate计算,其+的实现:
- public static final class LongDelegate extends ELArithmetic
- {
- protected Number add(Number num0, Number num1)
- {
- return Long.valueOf(num0.longValue() + num1.longValue());
- }
从这里我们可以看出其实现。
而且其规范中都规定了具体字面量的东西:
There are literals for boolean, integer, floating point, string, and null in an eval-
expression.
■ Boolean - true and false
■ Integer - As defined by the IntegerLiteral construct in Section 1.19
■ Floating point - As defined by the FloatingPointLiteral construct in
Section 1.19
■ String - With single and double quotes - " is escaped as \", ' is escaped as \',
and \ is escaped as \\. Quotes only need to be escaped in a string value enclosed
in the same type of quote
■ Null - null
也规定了操作符的运算规则,如+ - *:
- 1.3 Literals
- There are literals for boolean, integer, floating point, string, and null in an eval-expression.
- ■ Boolean - true and false
- ■ Integer - As defined by the IntegerLiteral construct in Section 1.19
- ■ Floating point - As defined by the FloatingPointLiteral construct in
- Section 1.19
- ■ String - With single and double quotes - " is escaped as \", ' is escaped as \',and \ is escaped as \\. Quotes only need to be escaped in a string value enclosed in the same type of quote
- ■ Null - null
- ■ If operator is -, return A.subtract(B)
- ■ If operator is *, return A.multiply(B)
- ■ If A or B is a Float, Double,or String containing ., e,or E:
- ■ If A or B is BigInteger, coerce both A and B to BigDecimal and apply operator.
- ■ Otherwise, coerce both A and B to Double and apply operator
- ■ If A or B is BigInteger, coerce both to BigInteger and then:
- ■ If operator is +, return A.add(B)
- ■ If operator is -, return A.subtract(B)
- ■ If operator is *, return A.multiply(B)
- ■ Otherwise coerce both A and B to Long and apply operator
- ■ If operator results in exception, error
如Integer型,直接交给前边介绍的IntegerLiteral。
即规范中其实已经规范了这些,但是就像java里的一些东西,虽然规范规定了(如排序时 很多人有时候使用 return a-b; 如果a是负数则可能溢出),但是还是很容易出错。