package cn;
public class A {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}
}
<%
A a1 = new A();
a1.setId(1);
A a2 = new A();
a2.setId(2);
List<A> list = new ArrayList();
list.add(a1);
list.add(a2);
request.setAttribute("list", list);
%>
<s:iterator value="#request.list" var="a">
<s:property value="#a in #request.list"/><br/>
</s:iterator>
</body>
</html>
期望輸出:
true
true
但是實際是:
true
如果配置struts.el.throwExceptionOnFailure=true,那麼會得到如下異常:
invalid comparison: cn.A and cn.A - Class: ognl.OgnlOps
File: OgnlOps.java
Method: compareWithConversion
原因在其ognl LanguageGuide 中也說了:
寫道
The ordering operators compare with compareTo() if their arguments are non-numeric and implement Comparable; otherwise, the arguments are interpreted as numbers and compared numerically. The in operator is not from Java; it tests for inclusion of e1 in e2, where e2 is interpreted as a collection. This test is not efficient: it iterates the collection. However, it uses the standard OGNL equality test.
它通過對象的compareTo去比較,且此處的in不是來自Java語言的。
所以如果你的對象沒有實現Comparable,那麼比較就會出問題,解決方案是:
1、實現Comparable來比較
2、使用集合本身自帶的contains
其實ognl完全可以規避這個問題,通過改造ognl.OgnlOps.compareWithConversion方法:
原來是:
case NONNUMERIC:
if ( ( t1 == NONNUMERIC ) && ( t2 == NONNUMERIC ) )
{
if ( ( v1 instanceof Comparable ) && v1.getClass().isAssignableFrom( v2.getClass() ) )
{
result = ( (Comparable) v1 ).compareTo( v2 );
break;
}
throw new IllegalArgumentException( "invalid comparison: " + v1.getClass().getName()
+ " and " + v2.getClass().getName() );
}
// else fall through
可以改造爲如下來解決:
case NONNUMERIC:
if ( ( t1 == NONNUMERIC ) && ( t2 == NONNUMERIC ) )
{
if ( ( v1 instanceof Comparable ) && v1.getClass().isAssignableFrom( v2.getClass() ) )
{
result = ( (Comparable) v1 ).compareTo( v2 );
break;
}
result = -1;
}
即最後不拋出異常,而是爲-1。
提交問題後(https://issues.apache.org/jira/browse/WW-4230),人家覺得沒改的必要,那就無所謂了,知道問題即可。